context.Request);} catch (SignatureVerificationException ex

时间:2022-04-17 07:57:41

1 API接口验证与授权

JWT

JWT界说,它包罗三部分:headerpayloadsignature;每一部分都是使用Base64编码的JSON字符串。之间以句号分隔断绝分手。signature”header.payload”经加密后的字符串。

给与JWT实现验证与授权查验机制,JWT格局为:

header

{

"typ": "JWT",

"alg": "HS256"

}

payloadappid为GUID,timestampunix时间戳

{

"appid": GUID,

"timestamp": Unix time

}

Signature使用HS256HMAC SHA-256,SHA Secure Hash Algorithm,安适散列算法headerpayload‘.’连接的字符串进行签名。

JWT加密:给与RSA加密算法对其进行加密。

密钥发放

发放给客户真个参数:appIdappSecretpublicKeyprivateKeyId。此中publicKeyRSA公钥,privateKeyId为处事端私钥Id。处事端或按照privateKeyId在缓存(本地或Redis等)中查找RSA私钥。

合成accessToken:header、payload与上述不异,签名密钥为appSecret。合成以后,使用publicKey对其进行加密。

合成headerJson:accessToken和privateKeyId组成的Json字符串,然后将字符串用Base64编码方法编码。

验证流程

客户端将上述headerB64放入请求头,向处事端倡议请求,处事端从请求头中拿到headerJson并解码headerJson,进而从中得到accessTokenprivateKeyId,处事端按照privateKeyId找到privateKey,使用privateKeyaccessToken解密,按照payload中的timestamp验证过期,若未过期,那么进行签名校验,验证通过授权用户端。

示例代码(关键性代码)

public abstract class BasicAuthenticationAttribute : Attribute, IAuthenticationFilter { public async Task AuthenticateAsync(HttpAuthenticationContext context, System.Threading.CancellationToken cancellationToken) { await Task.Factory.StartNew(()=> { //解析头信息,获得appid和timestamp var header = ... //如果未获得上述信息 if (header == null) { context.ErrorResult = new AuthenticationFailureResult(requestHeaderAnalysis.ExecStatus, context.Request); return; } //从缓存中获得RSA私钥 string privateKey= ... if (String.IsNullOrWhiteSpace(privateKey)) { context.ErrorResult = new AuthenticationFailureResult(StatusCodeManager.GetStatusInfo("B07", "a001"), context.Request); return; } //使用RSA私钥对AccessToken解密 string accessToken = Decrypt(requestHeaderInfo.AccessToken, privateKey); if (String.IsNullOrWhiteSpace(accessToken)) {//验证根据是空,设置错误信息 context.ErrorResult = new AuthenticationFailureResult(StatusCodeManager.GetStatusInfo("B05", "a001"), context.Request); return; } //从AccessToken的payload中获得appKey和timestamp(时间戳) var payloadDict = JsonWebToken.DecodeToObject(accessToken); string appKey = Convert.ToString(payloadDict["appKey"]); string timestamp = Convert.ToString(payloadDict["timestamp"]); //在处事端数据库中,按照appKey查找appSecret ApiAccount apiAccount = GetApiAccount(appKey); if (apiAccount==null||string.IsNullOrWhiteSpace(apiAccount.AppSecret)) { context.ErrorResult = new AuthenticationFailureResult(StatusCodeManager.GetStatusInfo("B05", "a001"), context.Request); return; } //验证是否超时,签名是否被篡改 try { //允许的时间段(小时转化为秒) JsonWebToken.Validate(accessToken, apiAccount.AppSecret, (int)AppSettings.TokenTimeout.TotalSeconds); } catch (TokenExpiredException ex) { context.ErrorResult = new AuthenticationFailureResult(StatusCodeManager.GetStatusInfo("B03", "a001"), context.Request); return; } catch (SignatureVerificationException ex) { context.ErrorResult = new AuthenticationFailureResult(StatusCodeManager.GetStatusInfo("B02", "a001"), context.Request); return; } }); //其他验证逻辑 await AuthenticateHockAsync(context, cancellationToken); } //// <summary> /// 子类中重写 /// 实现他验证逻辑 /// </summary> protected abstract Task AuthenticateHockAsync(HttpAuthenticationContext context, System.Threading.CancellationToken cancellationToken); /// <summary> /// 设置principal /// </summary> public Task ChallengeAsync(HttpAuthenticationChallengeContext context, System.Threading.CancellationToken cancellationToken) { return Task.FromResult(0); } public bool AllowMultiple { get { return true; } } }

2 用户授权

某些数据只有用户登陆了才华够获得,并且差此外用户对数据的访谒级别也不一样,为实现登陆验证与角色控制,给与以下方法。