# rpc错误：代码=权限被拒绝 描述=未认证：请求未通过身份验证

- **ID:** `go/grpc-permission-denied-auth-missing`
- **领域:** go
- **类别:** auth_error
- **验证级别:** ai_generated
- **修复率:** 80%

## 根因

gRPC调用缺少必需的身份验证凭据，例如令牌缺失或无效。

## 版本兼容性

| 版本 | 状态 | 引入 | 弃用 |
|------|------|------|------|
| 1.0 | active | — | — |
| 1.1 | active | — | — |

## 解决方案

1. **Attach a valid authentication token to the gRPC metadata.** (90% 成功率)
   ```
   token := "valid-jwt-token"
conn, err := grpc.Dial("localhost:8080", grpc.WithInsecure(), grpc.WithPerRPCCredentials(&authCreds{token: token}))
// Define authCreds implementing credentials.PerRPCCredentials
func (c *authCreds) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
    return map[string]string{"authorization": "Bearer " + c.token}, nil
}
func (c *authCreds) RequireTransportSecurity() bool { return false }
   ```
2. **Implement an interceptor to add credentials automatically.** (85% 成功率)
   ```
   func authInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
    md := metadata.Pairs("authorization", "Bearer token")
    ctx = metadata.NewOutgoingContext(ctx, md)
    return invoker(ctx, method, req, reply, cc, opts...)
}
conn, err := grpc.Dial("localhost:8080", grpc.WithInsecure(), grpc.WithUnaryInterceptor(authInterceptor))
   ```

## 无效尝试

- **Retry the request without adding any credentials.** — The server will continue to reject unauthenticated requests. (100% 失败率)
- **Use a hardcoded token that may be expired.** — Expired tokens are also rejected by the server. (90% 失败率)
