一、开发环境
VS2017 enterprise
win10 Pro 64
.net 4.6.2
二、开发过程
1、使用VS2017 创建.netframework项目,选择WebApi
2、从Nuget包中搜索并安装JWT
3、在Models中创建AuthInfo.cs、LoginRequest.cs、TokenInfo.cs三个类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace apiToken.Models
{
/// <summary>
/// 身份验证信息 模拟JWT的payload
/// </summary>
public class AuthInfo
{
/// <summary>
/// 用户名
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 角色
/// </summary>
public List<string> Roles { get; set; }
/// <summary>
/// 是否管理员
/// </summary>
public bool IsAdmin { get; set; }
/// <summary>
/// 口令过期时间
/// </summary>
public DateTime? ExpiryDateTime { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace apiToken.Models
{
/// <summary>
/// 登录用户信息
/// </summary>
public class LoginRequest
{
/// <summary>
/// 用户名
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 密码
/// </summary>
public string Password { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace apiToken.Models
{
/// <summary>
/// 生成的口令信息
/// </summary>
public class TokenInfo
{
/// <summary>
/// 是否成功
/// </summary>
public bool Success { get; set; }
/// <summary>
/// 令牌
/// </summary>
public string Token { get; set; }
/// <summary>
/// 错误信息
/// </summary>
public string Message { get; set; }
}
}
4、在Controllers文件夹下创建TokenController.cs文件,生成口令
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using apiToken.Models;
using System.Text;
namespace apiToken.Controllers
{
[RoutePrefix("api/Token")]
public class TokenController : ApiController
{
/// <summary>
/// 登录
/// </summary>
/// <param name="loginRequest"></param>
/// <returns></returns>
[HttpPost]
[Route("Login")]
public TokenInfo Login([FromBody] LoginRequest loginRequest)
{
TokenInfo tokenInfo = new TokenInfo();//需要返回的口令信息
if (loginRequest != null)
{
string userName = loginRequest.UserName;
string passWord = loginRequest.Password;
bool isAdmin = (userName == "admin")?true:false;
//模拟数据库数据,真正的数据应该从数据库读取
//身份验证信息
AuthInfo authInfo = new AuthInfo { UserName=userName,Roles=new List<string> {"admin","commonrole"}, IsAdmin= isAdmin, ExpiryDateTime=DateTime.Now.AddHours(2)};
const string secretKey = "Hello World";//口令加密秘钥
try
{
byte[] key = Encoding.UTF8.GetBytes(secretKey);
IJwtAlgorithm algorithm = new HMACSHA256Algorithm();//加密方式
IJsonSerializer serializer = new JsonNetSerializer();//序列化Json
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();//base64加解密
IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);//JWT编码
var token = encoder.Encode(authInfo, key);//生成令牌
//口令信息
tokenInfo.Success = true;
tokenInfo.Token = token;
tokenInfo.Message = "OK";
}
catch(Exception ex)
{
tokenInfo.Success = false;
tokenInfo.Message = ex.Message.ToString();
}
}
else
{
tokenInfo.Success = false;
tokenInfo.Message = "用户信息为空";
}
return tokenInfo;
}
}
}
5、在项目中添加AuthAttributes文件夹,并且在文件夹在创建ApiAuthorizeAttribute.cs文件,用于创建身份拦截器
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
using JWT;
using JWT.Serializers;
using apiToken.Models;
using System.Text;
using System.Net;
using System.Net.Http;
namespace apiToken.AuthAttributes
{
/// <summary>
/// 身份认证拦截器
/// </summary>
public class ApiAuthorizeAttribute: AuthorizeAttribute
{
/// <summary>
/// 指示指定的控件是否已获得授权
/// </summary>
/// <param name="actionContext"></param>
/// <returns></returns>
protected override bool IsAuthorized(HttpActionContext actionContext)
{
//前端请求api时会将token存放在名为"auth"的请求头中
var authHeader = from t in actionContext.Request.Headers where t.Key == "auth" select t.Value.FirstOrDefault();
if (authHeader != null)
{
const string secretKey = "Hello World";//加密秘钥
string token = authHeader.FirstOrDefault();//获取token
if (!string.IsNullOrEmpty(token))
{
try
{
byte[] key = Encoding.UTF8.GetBytes(secretKey);
IJsonSerializer serializer = new JsonNetSerializer();
IDateTimeProvider provider = new UtcDateTimeProvider();
IJwtValidator validator = new JwtValidator(serializer, provider);
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder);
//解密
var json = decoder.DecodeToObject<AuthInfo>(token, key, verify: true);
if (json != null)
{
//判断口令过期时间
if (json.ExpiryDateTime < DateTime.Now)
{
return false;
}
actionContext.RequestContext.RouteData.Values.Add("auth", json);
return true;
}
return false;
}
catch (Exception ex)
{
return false;
}
}
}
return false;
}
/// <summary>
/// 处理授权失败的请求
/// </summary>
/// <param name="actionContext"></param>
protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
{
var erModel = new
{
Success="false",
ErrorCode="401"
};
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.OK, erModel, "application/json");
}
/// <summary>
/// 为操作授权时调用
/// </summary>
/// <param name="actionContext"></param>
//public override void OnAuthorization(HttpActionContext actionContext)
//{
//}
}
}
6、创建UserInfoController.cs 用于测试身份验证
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using apiToken.AuthAttributes;
using Newtonsoft.Json;
namespace apiToken.Controllers
{
[RoutePrefix("api/UserInfo")]
[ApiAuthorize]
public class UserInfoController : ApiController
{
/// <summary>
/// 获取用户信息
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("GetUserInfo")]
public string GetUserInfo()
{
var userInfo = new
{
UserName="test",
Tel="123456789",
Address="testddd"
};
return JsonConvert.SerializeObject(userInfo);
}
}
}
最后将webapi接口在IIS中发布,通过PostMan进行测试
如果Token不正确或者Token失效则不会进入请求
注:如果遇到跨域的问题,可以下webconfig中做如下配置
想要更详细的了解Nuget中的JWT的使用,可通过此链接学习https://github.com/jwt-dotnet/jwt
需要源码程序可同学可通过此链接下载 https://download.csdn.net/download/liwan09/10769921
---------------------
作者:蓝晶之心
来源:CSDN
原文:https://blog.csdn.net/liwan09/article/details/83820651
版权声明:本文为博主原创文章,转载请附上博文链接!