.NET、VUE利用RSA加密完成登录并且发放JWT令牌设置权限访问

后端生成公钥私钥

使用RSA.ToXmlString(Boolean) 方法生成公钥以及私钥。

cs 复制代码
RSACryptoServiceProvider rSA = new();
string pubKey = rSA.ToXmlString(false);//公钥
string priKey = rSA.ToXmlString(true);//私钥

后端将生成的公钥发送给前端

创建一个get请求,将后端生成的公钥发送给前端,需要注意,这里生成的公钥是XML格式需要转换为pkcs8格式,前端JS只能处理pkcs8格式,私钥不能发给前端!!!!

这里需要安装一个包XC.RSAUtil用于转换格式。

Install-Package XC.RSAUtil -Version 1.3.6

cs 复制代码
[HttpGet]
public object Edd()
{
    var keyList = RsaKeyConvert.PublicKeyXmlToPem(pubKey);//将xml格式转换为Pkcs8
    return keyList;
}

前端使用公钥加密密码

使用的加密库为JSEncrypt库,安装JSEncrypt库。

npm install jsencrypt -D

页面引用

javascript 复制代码
import {JSEncrypt} from 'jsencrypt'

界面

javascript 复制代码
<div id="JWT">
	<div>
		账号:<input type="text" v-model="MyName"/>
	</div>
	<div>
		密码:<input type="text" v-model="MyPassword"/>
	</div>
	<button @click="Myinput">登录</button>
</div>

保存账号密码以及后端发送过来的公钥。

javascript 复制代码
data() {
	return {
		MyName: null,//账号
		MyPassword: null,//密码
		pubKey:null,//公钥
        JWTkey:null//JWT令牌
	}
}

在使用登录界面时调用函数接收公钥并且保存。

javascript 复制代码
created() {
	PostJwtEdd().then(res=>{
		this.pubKey=res
	}).catch(err => {
		console.log(err)
	})
}

前端在输入账号密码后,对密码进行加密,将加密后的密码发送请求给后端,对比成功后前端将JWT令牌保存。

javascript 复制代码
methods:{
	Myinput(){
		var encryptor = new JSEncrypt()
		encryptor.setPublicKey(this.pubKey)
		var rsaPassWord = encryptor.encrypt(this.MyPassword)//加密密码
		PostJwtDdd(this.MyName, rsaPassWord).then(res => {
			this.JWTkey=res//将后端生成的JWT令牌保存
		}).catch(err => {
			console.log(err)
		})
	}
}

发送密码的axio请求部分

javascript 复制代码
export function PostJwtDdd(MyName,MyPassword){
	return request({
		method: 'post',
		url: '/JWTS/Ddd',
		data:{
			MyName,
			MyPassword
		}
	})
}

这是发送的账号以及密码密文。

后端接收参数对比

后端接收得到参数,将密码密文进行解密。

创建一个类用于接收账号和加密后的密文。

cs 复制代码
public class RsaKey
{
   public string MyName { get; set; }
   public string MyPassword { get; set; }
}

接收参数开始解密对比账号密码。

cs 复制代码
[HttpPost]
public object Ddd([FromBody] RsaKey rsaKey)
{
    rsa.FromXmlString(priKey);//传入私钥进行解密
    byte[] cipherbytex;
    cipherbytex = rsa.Decrypt(Convert.FromBase64String(rsaKey.MyPassword), false);
    var c = Encoding.UTF8.GetString(cipherbytex);//转换为string类型
    MyDbContext md = new MyDbContext();//对数据库表创建实体类
    var user = md.MyIntroductions.Where(x => x.MyName == rsaKey.MyName).Select(x => x.MyPassword);//数据库中寻找该账号对应的密码
    string users = null;
    foreach (var v in user)
    {
        users = v;
    }
    if (user == null)
    {
        return new { err = "账号错误" };
    }
    else
    {
        if (users == c)
        {
            //登录成功
        }
        else
        {
            return new { err = "密码错误" };
        }
    }
}

生成JWT令牌

登录成功之后开始生成JWT令牌并且返回给前端,在登录成功哪里生成。

需要安装两个包。

包1:System.IdentityModel.Tokens.Jwt

Install-Package System.IdentityModel.Tokens.Jwt

包2:Microsoft.AspNetCore.Authentication.JwtBearer

Install-Package Microsoft.AspNetCore.Authentication.JwtBearer

cs 复制代码
List<Claim> claims = new List<Claim>();
claims.Add(new Claim("MyName", rsaKey.MyName));
claims.Add(new Claim(ClaimTypes.Role, rsaKey.MyName));//颁发管理员角色
string key = jwtSettingsOpt.Value.SecKey;
DateTime expire = DateTime.Now.AddSeconds(jwtSettingsOpt.Value.ExpireSeconds);
byte[] secBytes = Encoding.UTF8.GetBytes(key);
var seckey = new SymmetricSecurityKey(secBytes);
var credentials = new SigningCredentials(seckey, SecurityAlgorithms.HmacSha256Signature);
var tokenDescriptor = new JwtSecurityToken(claims: claims, expires: expire, signingCredentials: credentials);
string jwt = new JwtSecurityTokenHandler().WriteToken(tokenDescriptor);
return jwt;

这是前端接收到的JWT令牌

后端权限访问

后端创建一个post请求,该请求带有Authorize

Authorize是一个用于处理权限的,在这里的作用就是对没有JWT令牌的请求返回401错误,也就是我们可以利用这一点来对登录的用户开放一些权限,如果没有JWT令牌那么就无法请求到数据。

该post请求会返回请求人的账号。

cs 复制代码
[Authorize]
[HttpPost]
public object Bdd()
{
    return this.User.FindFirst("MyName")!.Value;
}

前端带JWT令牌进行访问

需要注意的是JWT令牌是通过'Authorization'的一个请求头发送过去,格式必须为:

Authorization:Bearer+一个空格+后端生成的JWT令牌

前端界面

javascript 复制代码
<button @click="MyJwt">查看权限</button>
javascript 复制代码
MyJwt(){
	var JwtKey='Bearer '+this.JWTkey
	console.log(JwtKey)
	PostJwtBdd(JwtKey).then(res=>{
		console.log(res)
	}).catch(err=>{
		console.log(err)
	})
}

axios请求部分

javascript 复制代码
export function PostJwtBdd(JwtKey){
	return request({
		method: 'post',
		url: '/JWTS/Cdd',
		headers: {
			'Authorization': JwtKey
		}
	})
}

在后端请求中配置了Authorize(Roles ="admin")后,只有在Roles指定的用户才能对其接口进行访问,一般可以用于对管理员的访问,在生成JWT令牌的时候,

通过claims.Add(new Claim(ClaimTypes.Role, '用户'));来进行匹配,管理员用户。

该post请求只有用户为admin的才能请求

cs 复制代码
[Authorize(Roles ="admin")]//配置只有管理员角色才能请求
[HttpPost]
public object Cdd()
{
      return this.User.FindFirst("MyName")!.Value;
}

前端界面

javascript 复制代码
<button @click="OneJwt">管理员权限</button>
javascript 复制代码
OneJwt(){
	var JwtKey='Bearer '+this.JWTkey
	console.log(JwtKey)
	PostJwtCdd(JwtKey).then(res=>{
	console.log(res)
	}).catch(err=>{
	console.log(err)
	})
}

axios请求部分,同样请求也只能通过'Authorization': 请求头进行发送。

Authorization+"空格"+生成的JWT令牌

javascript 复制代码
export function PostJwtCdd(JwtKey){
	return request({
		method: 'post',
		url: '/JWTS/Cdd',
		headers: {
			'Authorization': JwtKey
		}
	})
}

如果带有的是错误的JWT令牌,那么后端会返回401错误,如图所示:

并且不会返回任何的对象。

相关推荐
m0_敲代码的彭于晏1685 小时前
Vercel 前端部署平台深度评测
前端
2301_32241428045 小时前
基于SpringBoot+Vue的休闲零食超市管理系统的设计与实现59004-计算机毕设 原创(免费领源码+部署教程+开发环境)
java·vue.js·spring boot·redis·mysql·决策树·推荐算法
怕浪猫7 小时前
外包和大厂的前端代码,差在凌晨三点
前端·面试·github
m0_敲代码的彭于晏1687 小时前
Vercel 前端部署与全栈开发实战指南
前端·状态模式
徐小夕7 小时前
花了3个月,我们做了一款 AI 版的“飞书文档”
前端·算法·github
贾伟康7 小时前
【化学实验室|17】HarmonyOS ArkTS 亮暗色与视觉令牌实战:集中颜色、间距和交互状态避免页面割裂
前端·移动开发·harmonyos·arkts·arkui
Csvn8 小时前
SSR/SSG/ISR(上):峡谷与渲染策略的时间预算
前端
Csvn8 小时前
SSR/SSG/ISR(下):可交互性、新鲜度与回源账
前端
酷炫码神9 小时前
Day 10|Pinia 状态管理:把散落在各组件的数据,收进一个全局仓库
android·开发语言·javascript
Elcker11 小时前
YnuoAgent(依诺):一个 npm 包,跑起属于自己的 AI 研发平台
前端·人工智能·npm