简单口述一下这个JWT Token验证和Attribute拦截器在项目中起到的作用
一.Token存在的意义
Token的存是为了实现接口安全,比如当接口地址泄露了,别人随便就能访问了,当我们有了Token,当别人知道了我们的接口地址,他们没有Token,我们后台检测到token为空,就会返回请求错误
二.Attribute拦截器的意义
就是相当于别人调用你的接口方法,我们加了拦截器,别人调用我们接口的时候就会先进入拦截器,我们就可以先在拦截器里面做一个校验什么的操作了,当然拦截器有进入方法前,返回值前,返回值后等的拦截器,前面的文章我有写到过
三.JWT Token验证结合Attribute拦截器在项目中的使用流程简单描述(表达能力略差)
第一步:客户端登录
第二步:验证用户名和密码以及添加Token
第三步:当用户名密码验证通过且Token生成成功,则返回验证成功状态和token值给前端页面
第四步:前端页面接收到返回验证成功状态和token值则把token值存到页面缓存之中(怎么存都行看你们自己)
第五步:当我们进入主页做其它功能请求接口时,先获取页面缓存中的token,携带token请求接口
第六步:当我们请求方法时,方法加了拦截器,就会先进入拦截器,就会判断这个token是否存在且token值正确
第七步:当token传输过来无误就会解析token存储到请求上下文Request上下文中(这个解析之后你们也可以不用一定存储到Request上下文中,根据情况而定)
第八步:然后再进入请求的接口方法体中进行数据操作
下面开始我们Demo实战演习............................................................
1.添加项目
2.添加model
using System.Collections.Generic;
namespace JwtWebApi.Models
{
public class AuthInfo
{
//模拟JWT的payload
public string UserName { get; set; }
public List Roles { get; set; }
public bool IsAdmin { get; set; }
///
/// 过期时间
///
public string ExpirationTime { get; set; }
}
}
namespace JwtWebApi.Models
{
public class LoginRequest
{
public string UserName { get; set; }
public string Password { get; set; }
}
}
namespace JwtWebApi.Models
{
public class LoginResult
{
public bool Success { get; set; }
public string Token { get; set; }
public string Message { get; set; }
}
}
3.添加拦截器(创建一个文件夹Attributes)添加一个ApiAuthorizeAttribute类
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using JwtWebApi.Models;
using System;
using System.Linq;
using System.Web.Http;
using System.Web.Http.Controllers;
namespace JwtWebApi.Attributes
{
///
/// 拦截器
///
public class ApiAuthorizeAttribute: AuthorizeAttribute
{
///
/// 验证请求是否携带token
///
///
///
protected override bool IsAuthorized(HttpActionContext actionContext)
{
//获取token
var authHeader = from t in actionContext.Request.Headers
where t.Key == "auth"
select t.Value.FirstOrDefault();
//验证token是否为空
if (authHeader != null)
{
string token = authHeader.FirstOrDefault();
if (!string.IsNullOrEmpty(token))
{
try
{
const string secret = "To Live is to change the world";
//secret需要加密
JWT.IJsonSerializer serializer = new JsonNetSerializer();
IDateTimeProvider provider = new UtcDateTimeProvider();
IJwtValidator validator = new JwtValidator(serializer, provider);
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, algorithm);
var authInfo = decoder.DecodeToObject(token, secret, verify: true);
if (authInfo != null)
{
//验证token是否超时,这里设置的过期时间为两小时
if (Convert.ToDateTime(authInfo.ExpirationTime) < DateTime.Now.AddHours(2) && !string.IsNullOrEmpty(authInfo.ExpirationTime))
{
actionContext.RequestContext.RouteData.Values.Add("autninfoDate", authInfo);
return true;
}
else return true;
}
return false;
}
catch (Exception ex)
{
return false;
}
}
}
return false;
}
}
}
4.创建Controller
SignInController 控制器
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using JwtWebApi.Models;
using System;
using System.Collections.Generic;
using System.Web.Http;
namespace JwtWebApi.Controllers
{
public class SignInController : ApiController
{
///
/// 登录/生成token
///
/// 用户名
/// 密码
///
[HttpGet]
public LoginResult Post(string UserName,string PassWord)
{
LoginResult rs = new LoginResult();
//这是是获取用户名和密码的,这里只是为了模拟
AuthInfo info = new AuthInfo {
UserName = UserName, //用户名
Roles = new List { "Admin", "Manage","YQ" }, //权限
IsAdmin = true,
ExpirationTime = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") };//过期时间
try
{
const string secret = "To Live is to change the world";
//secret需要加密
IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
IJsonSerializer serializer = new JsonNetSerializer();
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
var token = encoder.Encode(info, secret);
#region 模拟数据库存
//登录用户名密码验证
List list=new List();
list.Add(new LoginRequest { UserName = "admin", Password = "admin" });
#endregion
//且数据库有这用户才能登录成功
if (list.Exists(t => t.UserName == UserName && t.Password == PassWord)==false)
return new LoginResult { Message = "登录失败,账号或密码错误!", Success = false };
//验证token是否为空
if (token==null || token=="")
return new LoginResult { Message = "登录失败,token生成失败!", Success = false };
return new LoginResult { Message = "登录成功!", Token = token, Success = true };
}
catch (Exception ex)
{
//异常返回
return new LoginResult { Message = ex.Message, Success = false };
}
}
}
}
UserController 控制器
using JwtWebApi.Attributes;
using JwtWebApi.Models;
using System.Web.Http;
namespace JwtWebApi.Controllers
{
public class UserController : ApiController
{
///
/// 获取测试token
///
///
[ApiAuthorize]
[HttpGet]
public string Get11()
{
AuthInfo info = RequestContext.RouteData.Values["autninfoDate"] as AuthInfo;
if (info == null)
{
return "获取不到,失败";
}
else
{
return $"获取到了,Auth的Name是 {info.UserName}";
}
}
}
}
5.更改Home/Index页面内容
index页面内容
完结撒花........