接上文覆获,http://www.reibang.com/p/c5f9ea3b4b65 ASP.NET Core 2.1 JWT Token (一)弧可。
如下演示在項(xiàng)目中的 簡(jiǎn)單 的 實(shí)際使用方式:
在后端生成token
1.在Startup.cs中配置 服務(wù) 蛀柴,添加jwt 驗(yàn)證 服務(wù)添加服務(wù) ( 在ConfigureServices方法中 )
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options => {
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,//是否驗(yàn)證Issuer
ValidateAudience = true,//是否驗(yàn)證Audience
ValidateLifetime = true,//是否驗(yàn)證失效時(shí)間
ValidateIssuerSigningKey = true,//是否驗(yàn)證SecurityKey
ValidAudience = "igbom_web",//Audience
ValidIssuer = "igbom_web",//Issuer吞滞,這兩項(xiàng)和前面簽發(fā)jwt的設(shè)置一致
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["SecurityKey"]))//拿到SecurityKey
};
});
2.啟用 ( 在Configure方法中 )
app.UseAuthentication();//注意添加這一句掰读,啟用jwt驗(yàn)證
3.添加驗(yàn)證邏輯 亡容, 登陸成功就發(fā)放 token 品洛。
public class HomeController : Controller
{
private IgbomContext _context;
private Common _common;
private readonly IConfiguration _configuration;
public HomeController(IgbomContext context, Common common, IConfiguration configuration)
{
_context = context;
_common = common;
_configuration = configuration;
}
//登錄操作
[HttpPost]
public JsonResult login([FromForm] User model)
{
UserMsg msg = new UserMsg()
{
mark = 0,
msg = "",
token = "",
};
User user = _context.User.Where(x => x.name == model.name).FirstOrDefault();
string password_form = _common.Get_MD5_Method1(model.password);
if (user != null && user.password == password_form.ToLower())
{
JwtTokenUtil jwtTokenUtil = new JwtTokenUtil(_configuration);
string token = jwtTokenUtil.GetToken(user); //生成token
//var headers = new HttpResponseMessage().Headers;
//headers.Add("Authorization",token);
msg.mark = 1;
msg.msg = "登錄成功";
msg.token = token;
}
else
{
msg.msg = "用戶名或者密碼錯(cuò)誤";
}
return Json(msg);
}
}*/
/*
public class UserMsg {
//0是錯(cuò)誤树姨,1 是正確的
public int mark { get; set; }
public string msg { get; set; }
public string token { get; set; }
}*/
4 .創(chuàng)建JwtTokenUtil工具類,用于生成Jwt Token桥状。
public class JwtTokenUtil
{
private readonly IConfiguration _configuration;
public JwtTokenUtil(IConfiguration configuration)
{
_configuration = configuration;
}
public string GetToken(User user)
{
// push the user’s name into a claim, so we can identify the user later on.
var claims = new[]
{
new Claim(ClaimTypes.Name, user.name),
//new Claim(ClaimTypes.Role, admin)//在這可以分配用戶角色帽揪,比如管理員 、 vip會(huì)員 辅斟、 普通用戶等
};
//sign the token using a secret key.This secret will be shared between your API and anything that needs to check that the token is legit.
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["SecurityKey"])); // 獲取密鑰
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); //憑證 转晰,根據(jù)密鑰生成
//.NET Core’s JwtSecurityToken class takes on the heavy lifting and actually creates the token.
/**
* Claims (Payload)
Claims 部分包含了一些跟這個(gè) token 有關(guān)的重要信息。 JWT 標(biāo)準(zhǔn)規(guī)定了一些字段士飒,下面節(jié)選一些字段:
iss: The issuer of the token查邢,token 是給誰(shuí)的 發(fā)送者
aud: 接收的
sub: The subject of the token,token 主題
exp: Expiration Time酵幕。 token 過(guò)期時(shí)間扰藕,Unix 時(shí)間戳格式
iat: Issued At。 token 創(chuàng)建時(shí)間芳撒, Unix 時(shí)間戳格式
jti: JWT ID邓深。針對(duì)當(dāng)前 token 的唯一標(biāo)識(shí)
除了規(guī)定的字段外未桥,可以包含其他任何 JSON 兼容的字段。
* */
var token = new JwtSecurityToken(
issuer: "igbom_web",
audience: "igbom_web",
claims: claims,
expires: DateTime.Now.AddMinutes(1),
signingCredentials: creds
);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
然后在前端使用token
5 . 可以通過(guò)Vuex管理token 芥备, 在store.js添加token冬耿,
token: "",
6 . 在 index.js 中為axios的每個(gè)請(qǐng)求添加 headers,以便每次發(fā)送請(qǐng)求的時(shí)候都在 headers中攜帶token萌壳。
Vue.prototype.$http.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('token');
7 . 添加 全局路由守衛(wèi) 亦镶, 在每次路由發(fā)生變化的時(shí)候都判斷本地 localStorage中是否有token。如果有袱瓮,就路由跳轉(zhuǎn)染乌,沒有就跳轉(zhuǎn)到登陸頁(yè)面。#<注意>:判斷路由變化的時(shí)候注意防止 進(jìn)入死循環(huán)
router.beforeEach((to, from, next) => {
if (localStorage.getItem('token') != '') {//store.state.token
console.log("333")
next()
}
else {
console.log("444")
if (to.path == '/userlogin' || to.path == '/login') {//如果是登錄頁(yè)面路徑懂讯,就直接next()
next();
} else {//不然就跳轉(zhuǎn)到登錄;
//再用一個(gè) if else判斷台颠,防止死循環(huán)
if (from.path.indexOf('/index') != -1) {
next('/userlogin');
}
else {
next('/login');
}
//next('/userlogin');
}
}
})
8 . 添加一個(gè)登陸頁(yè)面褐望,在login.vue中,發(fā)送表單數(shù)據(jù)串前,如果登陸成功瘫里,拿到token,就將token 存放到本地荡碾。
this.$http.post('/Home/login', formData).then(function (res) {
if (res.data.mark == 1 && res.data.token != '') {
//保存token到狀態(tài)
that.$store.commit('changeToken', res.data.token); ///////提交狀態(tài)
localStorage.setItem('token', res.data.token);//////token保存到localStorage
that.$http.defaults.headers.common['Authorization'] = 'Bearer ' + res.data.token;
//跳轉(zhuǎn)到首頁(yè)
that.$router.push({
path: '/index/energymanagement'
});
} else {
//錯(cuò)誤提示
that.ruleForm2.errMsg = res.data.msg;
}
});
9.在普通頁(yè)面中谨读,每次發(fā)送api請(qǐng)求后返回結(jié)果的時(shí)候都要判斷,如果token過(guò)期了坛吁,跳轉(zhuǎn)到登陸頁(yè)面重新登陸劳殖。
.catch(){}
如果每次發(fā)送api請(qǐng)求后返回結(jié)果的時(shí)候都要判斷,那項(xiàng)目變大以后拨脉,很難維護(hù)哆姻,所以可以進(jìn)行一些封裝,
http://www.reibang.com/p/671410da8f60
至此玫膀,一個(gè)完整的token使用過(guò)程大致完成矛缨。
要理解JWT的使用,首先要清楚后端token生成帖旨,前端發(fā)送請(qǐng)求攜帶token的過(guò)程箕昭,然后針對(duì)這個(gè)過(guò)程去了解每個(gè)部分的實(shí)現(xiàn)。