RpcServerConf struct {
service.ServiceConf // 服务配置,详情见api配置说明,这里不赘述
ListenOn string // rpc监听地址和端口,如:127.0.0.1:8888
Etcd discov.EtcdConf `json:",optional"` // etcd相关配置
Auth bool `json:",optional"` // 是否开启Auth,如果是则Redis为必填
Redis redis.RedisKeyConf `json:",optional"` // Auth验证
StrictControl bool `json:",optional"` // 是否Strict模式,如果是则遇到错误是Auth失败,否则可以认为成功
// pending forever is not allowed
// never set it to 0, if zero, the underlying will set to 2s automatically
Timeout int64 `json:",default=2000"` // 超时控制,单位:毫秒
CpuThreshold int64 `json:",default=900,range=[0:1000]"` cpu降载阈值,默认900,可允许设置范围0到1000
}
2.认证初始化代码注解
// 默认的RPC验证有效时长
const defaultExpiration = 5 * time.Minute
// An Authenticator is used to authenticate the rpc requests.
// 一个身份验证器结构体用于验证rpc请求
type Authenticator struct {
store *redis.Redis
key string
cache *collection.Cache
strict bool
}
// NewAuthenticator returns an Authenticator.
// 新建一个身份验证器用于验证rpc请求,默认RPC验证有效时长为5分钟
func NewAuthenticator(store *redis.Redis, key string, strict bool) (*Authenticator, error) {
cache, err := collection.NewCache(defaultExpiration)
if err != nil {
return nil, err
}
return &Authenticator{
store: store,
key: key,
cache: cache,
strict: strict,
}, nil
}
3.RPC认证校验逻辑
注:
将Redis服务关闭后可测试RPC验证中的StrictControl选项,当StrictControl为true是严格的身份验证,即使认证过程中有错误,直接会提示认证失败,当其为false是非严格的身份验证,即验证过程中有出现错误(Redis无法链接,无法获取对应的key值等异常情况),也会提示认证成功
// Authenticate authenticates the given ctx.
// 对请求上下文进行身份验证。
func (a *Authenticator) Authenticate(ctx context.Context) error {
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
return status.Error(codes.Unauthenticated, missingMetadata)
}
apps, tokens := md[appKey], md[tokenKey]
if len(apps) == 0 || len(tokens) == 0 {
return status.Error(codes.Unauthenticated, missingMetadata)
}
app, token := apps[0], tokens[0]
if len(app) == 0 || len(token) == 0 {
return status.Error(codes.Unauthenticated, missingMetadata)
}
return a.validate(app, token)
}
// 请求的身份认证逻辑
func (a *Authenticator) validate(app, token string) error {
expect, err := a.cache.Take(app, func() (interface{}, error) {
return a.store.Hget(a.key, app)
})
if err != nil {
// 如果在认证过程中出现错误,且配置选项中的StrictControl为true,则将错误返回,并提示身份验证失败
if a.strict {
return status.Error(codes.Internal, err.Error())
}
// 为false时,即使验证过程出现错误,但仍提示认证成功
return nil
}
if token != expect {
return status.Error(codes.Unauthenticated, accessDenied)
}
return nil
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)