之前一篇博客讲了如何使用ASP.NET Core WebAPI进行Jwt的登录认证,那么这个接口的认证如何结合登录呢?原来的系统前台页面是用的ASP.NET,基本可以看作是静态的页面,而且原来的aspx那一套登录认证也没法用,于是可以自己手写一套,包含了登录、返回登录前的路由、接口token检查、校验有效性。
登录接口返回的数据大概是这样的
{
"username": "shajia_shan",
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoic2hhamlhX3NoYW4iLCJleHAiOjE1OTY0NDczMTksImlzcyI6InlvdXJkb21haW4uY29tIiwiYXVkIjoieW91cmRvbWFpbi5jb20ifQ.hYR7hk9auPNLMiFDiWEzFVky8N-Xy_oINopxXmTk1jE",
"expires_in": 10
}
Login.html
用户输入用户名密码,发送ajax请求获取token,并写入cookie。下次接口请求或者打开页面时校验token是否存在,是否在有效期内。
核心js如下
<script src="authutils.js"></script>
<script>
window.onload = function () {
return_url = checkLogin();
console.log(return_url)
};
function Login() {
var userInfo = {};
userInfo.username = document.getElementById("login-form-username").value;
userInfo.password = document.getElementById("login-form-password").value;
$.ajax({
url: "http://localhost:3019/api/v1/auth",
type: 'POST',
contentType: "application/json",
dataType: "json",
crossDomain: true,
data: JSON.stringify(userInfo),
//data: $('#login-form').serialize(),
success: function (data) {
Swal.fire(
'Login successfully!',
' ',
'success'
);
sleep(1500).then(() => {
var token = data["access_token"];
var expires_in = data["expires_in"];
setCookie(token, expires_in);
console.log(return_url);
window.location.href = return_url;
})
},
error: function() {
Swal.fire(
'Login failed!',
' ',
'error'
)
}
});
}
</script>
authutils.js
login_url = "http://xx.xx.xx.xx/Login.html";
default_url = "http://xx.xx.xx.xx/Index.html";
// 获取指定名称的cookie
function getCookie(name) {
var strcookie = document.cookie;//获取cookie字符串
var arrcookie = strcookie.split("; ");//分割
//遍历匹配
for (var i = 0; i < arrcookie.length; i++) {
var arr = arrcookie[i].split("=");
if (arr[0] == name) {
return arr[1];
}
}
return "";
}
// 获取url的参数
function getRequestVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (pair[0] == variable) {
return pair[1];
}
}
return (false);
}
// 获取域名后面的链接
function getUrlRelativePath(url) {
//var url = document.location.toString();
var arrUrl = url.split("//");
var start = arrUrl[1].indexOf("/");
var relUrl = arrUrl[1].substring(start);//stop省略,截取从start开始到结尾的所有字符
return relUrl;
}
// Login.html访问返回return_url
function getReturnUrl(variable) {
var query = window.location.href.substring(1);
var start = query.indexOf(variable);
var result = query.substring(start + variable.length + 1);
return result;
}
function setCookie(name, expires_in) {
//获取当前时间
var date = new Date();
var expires = expires_in;
//设置cookie有效期
date.setTime(date.getTime() + expires * 60 * 1000);
document.cookie = "token=" + name + "; expires=" + date.toGMTString();
}
// 暂停一下,提升用户体验
function sleep(time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
function checkLogin() {
var token = getCookie("token");
var return_url = getUrlRelativePath(window.location.href);
if (token === "") {
if (return_url.indexOf("Login.html") !== -1 ? true : false) {
return getReturnUrl("return_url");
}
window.location.href = login_url + "?return_url=" + return_url;
} else {
$.ajax({
url: "http://localhost:3019/api/v1/auth/checklogin/",
type: 'GET',
headers: {
"Authorization": "Bearer " + token + ""
},
success: function (data) {
if (window.location.href !== login_url) {
return false;
} else {
window.location.href = default_url;
}
}, error: function (data) {
if (data.status === 401) {
window.location.href = login_url + "?return_url=" + return_url;
}
}
});
return "";
}
}
这里后端的checkLogin函数很简单,就是尝试访问加了拦截器的接口,如果拦下来了,那么说明token过期了,否则表示token有效。
[HttpGet("checklogin")]
[Authorize]
public IActionResult CheckLogin() {
return Ok();
}