-
-
Notifications
You must be signed in to change notification settings - Fork 175
JWT验证集成
Henry edited this page Sep 10, 2019
·
1 revision
在API
数据交互过程中往往需要安全验证,但组件并不直接提供这方向面的支持;由于组件是基于标准HTTP协议的实现,所有基于这协议的验证规则都可以根据实际情况来扩展。以下是针对JWT
验证的一个扩展,并添加的服务应用中。为了实现这一验证功能需要添加一个相关组件System.IdentityModel.Tokens.Jwt
public class JWTHelper
{
private string mIssuer = null;
private string mAudience = null;
private SecurityKey mSecurityKey;
private SigningCredentials mSigningCredentials;
private TokenValidationParameters mTokenValidation = new TokenValidationParameters();
private JwtSecurityTokenHandler mJwtSecurityTokenHandler = new JwtSecurityTokenHandler();
public JWTHelper() : this(null, null)
{
}
public JWTHelper(string issuer, string audience, string key = "2qyg4coej88uqrono0xdmx4y0il5dn5y7b72tlb3imba677ht1p1xlfcnh36mk5u3xzjktfara29axvzk85apfplun7oslbe1m20c148p5d519kja5wvg7lmn5v4a5ou")
{
mIssuer = issuer;
mAudience = audience;
mSecurityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
if (string.IsNullOrEmpty(mIssuer))
{
mTokenValidation.ValidateIssuer = false;
}
else
{
mTokenValidation.ValidIssuer = mIssuer;
}
if (string.IsNullOrEmpty(mAudience))
{
mTokenValidation.ValidateAudience = false;
}
else
{
mTokenValidation.ValidAudience = mAudience;
}
mTokenValidation.IssuerSigningKey = mSecurityKey;
mSigningCredentials = new SigningCredentials(mSecurityKey, SecurityAlgorithms.HmacSha256);
Expires = 60 * 24;
}
public int Expires { get; set; }
public string CreateToken(string name, string role)
{
ClaimsIdentity claimsIdentity = new ClaimsIdentity();
claimsIdentity.AddClaim(new Claim("Name", name));
claimsIdentity.AddClaim(new Claim("Role", role));
var item = mJwtSecurityTokenHandler.CreateEncodedJwt(mIssuer, mAudience, claimsIdentity, DateTime.Now.AddMinutes(-5),
DateTime.Now.AddMinutes(100), DateTime.Now,
mSigningCredentials);
return item;
}
public ClaimsPrincipal ValidateToken(string token)
{
return mJwtSecurityTokenHandler.ValidateToken(token, mTokenValidation, out var securityToken);
}
public UserInfo GetUserInfo(string token)
{
UserInfo userInfo = new UserInfo();
if (!string.IsNullOrEmpty(token))
{
var info = ValidateToken(token);
ClaimsIdentity identity = info?.Identity as ClaimsIdentity;
userInfo.Name = identity?.Claims?.FirstOrDefault(c => c.Type == "Name")?.Value;
userInfo.Role = identity?.Claims?.FirstOrDefault(c => c.Type == "Role")?.Value;
}
return userInfo;
}
public struct UserInfo
{
public string Name;
public string Role;
}
}
以上封装只是简单地提供了用户名称和角色两项信息,不过一般情况这两信息可以满足普通验证的需要;如果有更多的信息需求可以根据实际情况添加,不过信息越多那对应的Token
内容就越大。
var token=JWTHelper.CreateToken(name, role);
通过以上代码创建一个JWT
的Token
可以通过虑器的方式引入到组件中,这样就可以在不修改控制器逻辑的情况进行安全验证。过虑器实现如下:
public class JWTFilter : FilterAttribute
{
public override bool Executing(ActionContext context)
{
string token = context.HttpContext.Request.Header[HeaderTypeFactory.AUTHORIZATION];
var user = Program.JWTHelper.GetUserInfo(token);
if (!string.IsNullOrEmpty(user.Name))
{
return true;
}
else
{
context.Result = new TextResult("token not found");
return false;
}
}
}
重写Executing
方法,获取请求头相关Token
信息并获取相关用户信息,当获取的用户名是正确的情况则返回true
继续执行,否则返回一个相关的错误信息。
public object GetToken(string name, string role)
{
return new TextResult(JWTHelper.CreateToken(name, role));
}
[JWTFilter]
public object GetTime()
{
return DateTime.Now;
}
以上有两个方法,一个是不需要验证创建并返回一个Token
,而另一个获取时间的方法则需要验证通过后才能获取。