最近项目要求,需要实现前后分离,前端采用html5,jquery,css,后端采用.net core5.0技术栈进行开发。由于前端每次发送请求都需要携带token信息,这样如果都写在前端的每个页面的ajax头部,则产生了很多重复的代码,最佳的方案是单独写一个$.ajaxSetup,这样每个页面就可以关注自己的核心业务即可。现在上代码
$.ajaxSetup的单独文件代码:
layui.use(['form', 'table'], function () { let $ = layui.jquery; let api="http://localhost:3000/api/";//默认.net core5.0后端端口为3000 $.ajaxSetup({ cache : false, /* headers : {//发送请求时,将token存入到头部,注意,这种写法会导致有时候发送ajax携带不上token "Authorization" :'Bearer '+localStorage.getItem("token")//从localStorage中取token },*/ async:false, beforeSend:function(xhr){//这种方式最佳 console.log('ajax开始发送前的准备,往头部放入token.........................................................'); let tokenStr=localStorage.getItem("token"); if(tokenStr!=null){ xhr.setRequestHeader('Authorization', 'Bearer '+tokenStr); } }, success(result,status,xhr){ console.log('来自jq.js的success的result值21:',result); console.log('来自jq.js的success的status值21:',status); console.log('来自jq.js的success的xhr值21:',xhr); }, //这里可以理解为token没有或者已经过期失效 error : function(xhr) { console.log('出错啦,错误代码22',xhr.status); }, complete: function (xhr) { console.log('进入complete23.........'); } }); $.ajaxData = { //方法1:刷新token的操作 refresh: function refreshToken(func) { $.ajax({ type: 'get', //contentType: 'application/json', url: api + "Login/RefreshToken", //注意,可以不传data域,直接从上面的ajaxSetup头部获取,后端从头部拿到过期的token //data: {'expiredToken': localStorage.getItem('token')},//注意,expiredToken必须跟后端刷新token方法变量名相同 dataType:"text", success(token){ //将获取的新token存储起来 console.log('刷新后的token为23',token); localStorage.setItem('token', token); func(); } }); return false; } }; }); 登录页面的写法:(核心部分)
<script> layui.use(['form','jquery'], function () { let $ = layui.jquery, form = layui.form, layer = layui.layer; //前后分离中,服务端端口号,及其控制层名称和对应方法 let api="http://localhost:3000/api/"; // 登录过期的时候,跳出ifram框架 if (top.location !== self.location) top.location = self.location; //到登录界面后,需要删除localStorage中存储的数据 localStorage.clear();
// 进行登录操作 form.on('submit(login)', function (data) { data = data.field; if (data.username === '') { layer.msg('用户名不能为空'); return false;//该语句表示不再继续执行下面的代码 } // console.log("uname",data.username); if (data.password === '') { layer.msg('密码不能为空'); return false;//该语句表示不再继续执行下面的代码 } //console.log("pwd",data.password); //此处ajax登录验证 $.ajax({ //请求类型 type:"post", url:api+"Login/LoginIn", //contentType: "application/json;charset=UTF-8",//不写contentType时,默认值是:application/x-www-form-urlencoded //data:JSON.stringify({"uname":data.username,"pwd":data.password}), data:{"uname":data.username,"pwd":data.password}, dataType:"text", success:function (result,status,xhr) { /* console.log("result",result);//result的值就是后端传过来的token console.log("status",status); console.log("xhr",xhr); console.log("xhr.status",xhr.status);*/ //将token保存到localstorage中 localStorage.setItem('token',result); layer.msg('登录成功', function () { window.location = '../index.html'; }); }, error:function (xhr) { if(xhr.status===404){ layer.msg('账号或者密码错误!'); } } }); //注意!在form.on事件中,非button点击事件中,需要额外添加return false;语句,否则会导致ajax的success和error中的返回值无法获取 //或者无法返回到前端页面的控制台上 return false;//使用return false阻止提交表单后的页面跳转行为 }); }); </script> 前端一个普通页面的嵌入方式
<script src="../lib/layui-v2.6.3/layui.js" charset="utf-8"></script> <script src="../js/jq.js" type="text/javascript"></script> <script> layui.use(['form', 'table'], function () { var $ = layui.jquery, form = layui.form, table = layui.table; let api="http://localhost:3000/api/"; //初始化时被调用 $(function () { getTableData(); return false; }); function getTableData(){ $.ajax({ //请求类型 type:"get", url:api+"Data/getTable", async:false, //contentType: "application/json;charset=UTF-8",//不写contentType时,默认值是:application/x-www-form-urlencoded //data:JSON.stringify({"uname":data.username,"pwd":data.password}), /*headers : {//发送请求时,将token存入到头部 "Authorization" :'Bearer '+localStorage.getItem("token")//从localStorage中取token },*/ data:{"page":1,"limit":10}, dataType:"text", success:function (result,status,xhr) { console.log('来自table的success的result值11:',result); console.log('来自table的success的status值11:',status); console.log('来自table的success的xhr值11:',xhr); //table.render(); }, error:function (xhr) { console.log('出错啦!xhr12',xhr); console.log('xhr.getResponseHeader(Token-Expired)12:',xhr.getResponseHeader('Token-Expired')); if(xhr.status===401&&xhr.getResponseHeader('Token-Expired')==='true'){ console.log('token已经过期,现在进行刷新操作11....................................................'); //getTableData(); //情况localStorage中token的存储 $.ajaxData.refresh(getTableData); } }/*, complete: function (xhr) { console.log('进入complete13.........'); //console.log('xhr.getAllResponseHeaders',xhr.getAllResponseHeaders()); console.log('xhr.getResponseHeader(Token-Expired)13:',xhr.getResponseHeader('Token-Expired')); if(xhr.status===401 && xhr.getResponseHeader('Token-Expired')==='true'){//token过期了 //接下来,进行token的刷新操作 console.log('token已经过期,重新发送ajax请求13...................................................'); $.ajaxData.refresh(getTableData); }else if(xhr.status===401){ console.log('未授权13'); //layer.msg('未授权'); }else if(xhr.status===500){ console.log('系统错误13',xhr); // layer.msg('系统错误:' + xhr.responseText); } }*/ }); } table.render({ elem: '#currentTableId', //url: api+'Data/getTable', toolbar: '#toolbarDemo', defaultToolbar: ['filter', 'exports', 'print', { title: '提示', layEvent: 'LAYTABLE_TIPS', icon: 'layui-icon-tips' }], cols: [[ {type: "checkbox", width: 50}, {field: 'id', width: 80, title: 'ID', sort: true}, {field: 'username', width: 80, title: '用户名'}, {field: 'sex', width: 80, title: '性别', sort: true}, {field: 'city', width: 80, title: '城市'}, {field: 'sign', title: '签名', minWidth: 150}, {field: 'experience', width: 80, title: '积分', sort: true}, {field: 'score', width: 80, title: '评分', sort: true}, {field: 'classify', width: 80, title: '职业'}, {field: 'wealth', width: 135, title: '财富', sort: true}, {title: '操作', minWidth: 150, toolbar: '#currentTableBar', align: "center"} ]], limits: [10, 15, 20, 25, 50, 100], limit: 15, page: true, skin: 'line' }); }); </script>
后端.net core方法
[Route("api/[controller]")]
[ApiController]
public class LoginController : ControllerBase
{
[HttpPost("LoginIn")]
public ActionResult Post([FromForm] string uname, [FromForm] string pwd)
{
string username =uname;
string password =pwd;
//验证账号密码
//判断用户输入的信息是否为空
if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
{
return NotFound();
}
//查询账号密码
List<Login> loginList= new LoginDAL().getLoginInfo(username,password);
if (loginList.Count > 0)//存在
{
Login login = loginList[0];
string tokenStr = TokenHelper.getToken(login.id, login.username);
return Ok(tokenStr);
}
else
{
return NotFound();
}
}
}
[HttpGet("RefreshToken")]
public ActionResult refreshToken()
{
//尝试从请求中获取头部的token信息,不需要单独传入值
var tokenStr = Request.Headers["Authorization"].ToString();
string tokenStr2 = tokenStr.Split(' ')[1];
//刷新token操作,见下一篇文章
string newToken = TokenHelper.refreshToken(tokenStr2);
return Ok(newToken);
}
}