.Net Core WebApi中,使用JWT身份认证与授权

一、在startup文件中配置身份认证

a.配置JWT身份认证:

这里有两种方式,我个人看来没任何差别,如果有需要指定事件之类的(如:认证成功,认证失败时,可以自己去配置它的事件)

第一种:

第二种:

创建认证参数对象的方法:

b.开启JWT身份认证:

这里还额外增加一个异常处理的中间件,在身份认证失败时会进入到这里自动进行处理

二、配置完毕之后,我们就要开发登录接口,让客户端登录获取到token,之后就可以通过token来请求了

a.登录接口

  1.  
    /// <summary>
  2.  
    /// 登录获取token CreateDate:2019-12-13 14:58:55;Author:Ling_bug
  3.  
    /// </summary>
  4.  
    /// <param name="userPara"></param>
  5.  
    /// <returns></returns>
  6.  
    [HttpPost]
  7.  
    [AllowAnonymous]
  8.  
    public ResponseModel<UserTokenInfo> Login([FromBody] UserLoginParameter userPara)
  9.  
    {
  10.  
    var result = new ResponseModel<UserTokenInfo>();
  11.  
    try
  12.  
    {
  13.  
    if (string.IsNullOrWhiteSpace(userPara.User))
  14.  
    {
  15.  
    throw new Exception("用户名不能为空!");
  16.  
    }
  17.  
    if (string.IsNullOrWhiteSpace(userPara.Password))
  18.  
    {
  19.  
    throw new Exception("密码不能为空!");
  20.  
    }
  21.  
     
  22.  
    //验证用户名和密码
  23.  
    var userInfo = _UserService.LoginToGetUserInfo(userPara);
  24.  
    var claims = new Claim[]
  25.  
    {
  26.  
    new Claim(nameof(ClaimTypes.Sid), userInfo.Id.ToString()),
  27.  
    new Claim(nameof(ClaimTypes.UserData), JsonConvert.SerializeObject(userInfo))
  28.  
    };
  29.  
     
  30.  
    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_Configuration.JwtSecurityKey));
  31.  
    //过期时间
  32.  
    var expires = DateTime.Now.AddMinutes(1);
  33.  
    var token = new JwtSecurityToken(
  34.  
    issuer: _Configuration.Issuer,
  35.  
    audience: _Configuration.Audience,
  36.  
    claims: claims,
  37.  
    notBefore: DateTime.Now,
  38.  
    expires: expires,
  39.  
    signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256));
  40.  
     
  41.  
    //生成Token
  42.  
    string jwtToken = new JwtSecurityTokenHandler().WriteToken(token);
  43.  
    result.Code = (int)HttpStatusCode.OK;
  44.  
    result.Data = new UserTokenInfo() { AccessToken = jwtToken, ExpireDate = expires };
  45.  
    result.Message = "授权成功!";
  46.  
    }
  47.  
    catch (Exception ex)
  48.  
    {
  49.  
    result.Message = ex.Message;
  50.  
    result.Code = (int)HttpStatusCode.InternalServerError;
  51.  
    }
  52.  
    return result;
  53.  
    }

b.登录业务层,以及dao层,我这里二合一了,模拟操作

c.一些对象:

c.1.ajax请求响应实体:

c.2.用户登录参数实体

c.3.用户登录成功用户信息

ok,登录接口也开发完毕了。

三、开启了JWT身份认证,也开发了登录接口,接下来就是使用了,我们在需要身份认证的接口上增加Authorize特性即可,若不需要身份认证,添加AllowAnonymous特性即可

好了,接下来我们来测试一下

前端请求:

a.调用登录接口:

b.设置全局ajax,带上指定请求头(这里要记得,使用Bearer+空格+token)

c.登录成功后,正常请求接口

看下测试结果:

没有token时,请求失败,无权限

登录获取token,并存储token,之后的请求全部带上token(登录方法不要加权限哦,否则死循环了)

再次请求刚才的接口

这里说下为什么在添加请求头信息时要使用Bearer+空格+token:

我们在拿到token之后,要将token添加到请求头中,在postman中如何操作呢?

在Authorization中添加token,type要选择Bearer Token

这个时候我们选择了Bearer Token,填写了token之后,看看请求的header中,postman是如何处理我们的token的

postman给我们处理的结果是Bearer+空格+token

所以我们在使用时也要注意这个,这是JWT自身限定的,没有办法

如果需要获取到当前用户信息来使用的话,还是跟.Net Core MVC中权限过滤器一样去使用User.FindFirstValue(key)

还有两种方式:

第一种:

  1.  
    /// <summary>
  2.  
    /// 获取当前用户信息 CreateDate:2019-12-13 14:59:14;Author:Ling_bug
  3.  
    /// </summary>
  4.  
    /// <returns></returns>
  5.  
    [HttpGet]
  6.  
    public IEnumerable<string> GetLoginUserInfo()
  7.  
    {
  8.  
    var result = new List<string>();
  9.  
    var taskGetAuth = _HttpContextAccessor.HttpContext.AuthenticateAsync();
  10.  
    var auth = taskGetAuth.Result;
  11.  
    if (auth.Succeeded)
  12.  
    {
  13.  
    var userClaimList = auth.Principal.Claims;
  14.  
    foreach (var item in userClaimList)
  15.  
    {
  16.  
    if (item.Type == "exp" || item.Type == "nbf")
  17.  
    {
  18.  
    result.Add(string.Format("{0} = {1}({2})", item.Type, JwtTimeToNormalDate(item.Value).ToString("yyyy-MM-dd HH:mm:ss"), item.Value));
  19.  
    }
  20.  
    else
  21.  
    {
  22.  
    result.Add(string.Format("{0} = {1}", item.Type, item.Value));
  23.  
    }
  24.  
    }
  25.  
    }
  26.  
    return result;
  27.  
    }

第二种:

  1.  
    /// <summary>
  2.  
    /// 获取当前用户信息第二种方式 CreateDate:2019-12-13 15:09:48;Author:Ling_bug
  3.  
    /// </summary>
  4.  
    /// <returns></returns>
  5.  
    [HttpGet]
  6.  
    public IEnumerable<string> GetLoginUserInfo1()
  7.  
    {
  8.  
    var result = new List<string>();
  9.  
    var user = User;
  10.  
    var userClaimList = user.Claims;
  11.  
    foreach (var item in userClaimList)
  12.  
    {
  13.  
    if (item.Type == "exp" || item.Type == "nbf")
  14.  
    {
  15.  
    result.Add(string.Format("{0} = {1}({2})", item.Type, JwtTimeToNormalDate(item.Value).ToString("yyyy-MM-dd HH:mm:ss"), item.Value));
  16.  
    }
  17.  
    else
  18.  
    {
  19.  
    result.Add(string.Format("{0} = {1}", item.Type, item.Value));
  20.  
    }
  21.  
    }
  22.  
     
  23.  
    return result;
  24.  
    }

将jwt时间转换为正常时间:

  1.  
    /// <summary>
  2.  
    /// JWT时间转换为正常日期 CreateDate:2019-12-13 14:58:26;Author:Ling_bug
  3.  
    /// </summary>
  4.  
    /// <param name="jwtTime"></param>
  5.  
    /// <returns></returns>
  6.  
    private DateTime JwtTimeToNormalDate(string jwtTime)
  7.  
    {
  8.  
    if (string.IsNullOrWhiteSpace(jwtTime))
  9.  
    {
  10.  
    throw new Exception("jwt时间为空!");
  11.  
    }
  12.  
    //格林威治:1970年01月01日00时00分00秒
  13.  
    //北京时间:1970年01月01日08时00分00秒
  14.  
    var begin = Convert.ToDateTime("1970-1-1 8:00:00");
  15.  
    return begin.AddSeconds(Convert.ToDouble(jwtTime));
  16.  
    }

原文地址:https://www.cnblogs.com/zxtceq/p/14027376.html