使用ASP.NET WEB API 进行 JWT授权登录(二)
前言
上一次,简单的普及了一波JWT
。现在,接下来是对JWT
的具体在项目如何使用的总结。
开发环境
电脑系统:WIN10 家庭版
开发工具:2019 VS
相关步骤
创建WEB API
这不再重复了,如果不知道怎么创建的,请回看以往得文章。
ASP.NET WebApi 学习与实践系列(1)---如何创建 WebApi
安装JWT
选中菜单中的 工具->NuGet包管理器->管理解决方案的NuGet程序包 找到JWT安装包,选中安装的项目,点击安装即可。如下图所示:
在Model
层创建实体
在项目中找到Models文件夹,需要添加以下类:
AuthInfo.cs
身份验证信息 模拟JWT的payload。
using System;
using System.Collections.Generic;
namespace myJWT.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; }
}
}
LoginRequest.cs
登录用户信息。
namespace myJWT.Models
{
/// <summary>
/// 登录用户信息
/// </summary>
public class LoginRequest
{
/// <summary>
/// 用户名
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 密码
/// </summary>
public string Password { get; set; }
}
}
TokenInfo.cs
获取令牌。
namespace myJWT.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; }
}
}
创建Token
控制器
在Controllers
文件夹中,创建一个Token
的控制类,根据用户名和密码获取Token
信息。如下代码所示:
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using myJWT.Models;
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Http;
namespace myJWT.Controllers
{
[RoutePrefix("api/Token")]
public class TokenController : ApiController
{
#region 登录
/// <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 = "GQDstcKsx0NHjPOuXOYg5MbeJ1XT0uFiwDVvVBrk";//口令加密秘钥
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;
}
#endregion
}
}
创建ApiAuthorizeAttribute
身份验证
在项目中创建AuthAttributes
文件夹,创建ApiAuthorizeAttribute.cs
类,如下代码所示:
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using myJWT.Models;
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Http;
namespace myJWT.Controllers
{
[RoutePrefix("api/Token")]
public class TokenController : ApiController
{
#region 登录
/// <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 = "GQDstcKsx0NHjPOuXOYg5MbeJ1XT0uFiwDVvVBrk";//口令加密秘钥
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;
}
#endregion
}
}
创建UserInfo
控制器
在Controllers
文件夹中,创建一个UserInfo
的控制器,用于模拟登录信息。如下代码所示:
using Newtonsoft.Json;
using System.Web.Http;
namespace myJWT.Controllers
{
[RoutePrefix("api/UserInfo")]
public class UserInfoController : ApiController
{
#region 获取用户信息
/// <summary>
/// 获取用户信息
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("GetUserInfo")]
[ApiAuthorize]
public string GetUserInfo()
{
var userInfo = new
{
UserName = "test",
Tel = "123456789",
Address = "testddd"
};
return JsonConvert.SerializeObject(userInfo);
}
#endregion
}
}
注意:这里需要引用在这之前创建的ApiAuthorize
身份验证,不能再使用Authorize
。否则,在进行请求的时候会出现已拒绝为请求授权
的问题,从而无法请求数据。
修改Web.Config
配置文件
解决跨域问题。如下图所示:
应用
在项目中创建一个TextHtml
文件夹,创建一个测试页面textDemo.html
页面。用于模拟前端发送请求数据。页面代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>测试页面</title>
<link href="../Content/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<div class="form-horizontal">
<fieldset style="width:90%;margin:10px auto;">
<legend>根据用户名和密码获取Token</legend>
<div class="form-group">
<label for="txtUserName" class="col-sm-2 control-label">登录名称:</label>
<div class="col-sm-10">
<input type="text" value="" id="txtUserName" class="form-control" placeholder="请输入登录名称" autocomplete="off" />
</div>
</div>
<div class="form-group">
<label for="txtUserPwd" class="col-sm-2 control-label">登录密码:</label>
<div class="col-sm-10">
<input type="password" value="" id="txtUserPwd" class="form-control" placeholder="请输入登录密码" autocomplete="off" />
</div>
</div>
<div class="form-group">
<div class="col-sm-2 control-label">
</div>
<div class="col-sm-10">
<button onclick="login()" class="btn btn-default">登录</button>
</div>
</div>
</fieldset>
</div>
<div class="form-horizontal">
<fieldset style="width:90%;margin:10px auto;">
<legend>根据Token获取用户信息</legend>
<div class="form-group">
<label for="txtUserName" class="col-sm-2 control-label">Token:</label>
<div class="col-sm-10">
<textarea id="txtToken" class="form-control" rows="3"></textarea>
</div>
</div>
<div class="form-group">
<label for="txtUserName" class="col-sm-2 control-label">用户信息:</label>
<div class="col-sm-10">
<textarea id="txtUserList" class="form-control" rows="8"></textarea>
</div>
</div>
<div class="form-group">
<div class="col-sm-2 control-label">
</div>
<div class="col-sm-10">
<button onclick="GetUseList()" class="btn btn-default">获取</button>
</div>
</div>
</fieldset>
</div>
<script src="../Scripts/jquery-3.4.1.min.js"></script>
<script src="../Scripts/bootstrap.min.js"></script>
<script type="text/javascript">
var m_token = "";
/*登录获取Token*/
function login() {
var m_txtUserName = $("#txtUserName").val();
var m_txtUserPwd = $("#txtUserPwd").val();
$.post("https://localhost:44325/api/Token/Login", { UserName: m_txtUserName, Password: m_txtUserPwd }, function (msg) {
if (msg.Message == "OK" && msg.Success == true) {
m_token = msg.Token;
$("#txtToken").val(m_token);
}
});
}
/*根据Token获取用户信息*/
function GetUseList() {
var m_token = $("#txtToken").val();
$.ajax({
url: "https://localhost:44325/api/UserInfo/GetUserInfo",
headers: { "auth": m_token },
type: "GET",
success: function (msg) {
$("#txtUserList").html(msg);
}
});
}
</script>
</body>
</html>
界面效果如下如所示:
根据用户名和密码获取Token
在测试页面,输入用户名和密码,获取Token
。如下图所示:
根据Token
获取数据
通过Ajax``headers
中携带Token
进行数据请求。如下图所示:
总结
以上,就是通过JWT
的方式进行的身份授权验证。以上,都是经过实践过后的结果。如果,有不懂得,或者有不妥地方,随时留言。