侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

layui登录后token问题详解

前端  /  管理员 发布于 4年前   808

layui是一个非常简单且实用的后台管理系统搭建框架,里面的插件丰富使用简单,只需要在原有基础上进行修改即可,但是在数据处理方面略显薄弱,内置的jquery在实际过程中略显不足,若是能添加内置的mvc模式框架那就更好了

先介绍layui在登录这一块的使用,

登录问题主要是在token的存储调用上,先贴出后台的创建token以及拦截器的代码

首先引入jar包

<dependency>            <groupId>io.jsonwebtoken</groupId>            <artifactId>jjwt</artifactId>            <version>0.7.0</version>            <exclusions>                <exclusion>                    <artifactId>jackson-databind</artifactId>                    <groupId>com.fasterxml.jackson.core</groupId>                </exclusion>            </exclusions>        </dependency>

token使用io.jsonwebtoken ,可以自定义秘钥,并存储登录信息

package com.zeus.utils;import cn.hutool.json.JSON;import cn.hutool.json.JSONObject;import cn.hutool.json.JSONUtil;import com.zeus.constant.CommonConstants;import io.jsonwebtoken.Claims;import io.jsonwebtoken.JwtBuilder;import io.jsonwebtoken.Jwts;import io.jsonwebtoken.SignatureAlgorithm;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.crypto.spec.SecretKeySpec;import javax.xml.bind.DatatypeConverter;import java.security.Key;import java.util.Date;public class TokenUtil {    private static Logger LOG = LoggerFactory.getLogger(TokenUtil.class);    /**     * 创建TOKEN     *     * @param id, issuer, subject, ttlMillis     * @return java.lang.String     * @methodName createJWT     * @author fusheng     * @date 2019/1/10     */    public static String createJWT(String id, String issuer, String subject, long ttlMillis) {        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;        long nowMillis = System.currentTimeMillis();        Date now = new Date(nowMillis);        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary("englishlearningwebsite");        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());        JwtBuilder builder = Jwts.builder().setId(id)                .setIssuedAt(now)                .setSubject(subject)                .setIssuer(issuer)                .signWith(signatureAlgorithm, signingKey);        if (ttlMillis >= 0) {            long expMillis = nowMillis + ttlMillis;            Date exp = new Date(expMillis);            builder.setExpiration(exp);        }        return builder.compact();    }    /**     * 解密TOKEN     *     * @param jwt     * @return io.jsonwebtoken.Claims     * @methodName parseJWT     * @author fusheng     * @date 2019/1/10     */    public static Claims parseJWT(String jwt) {        Claims claims = Jwts.parser()                .setSigningKey(DatatypeConverter.parseBase64Binary("englishlearningwebsite"))                .parseClaimsJws(jwt).getBody();        return claims;    }}

解密主要使用到 parseJWT 方法

public static Contact getContact(String token) {        Claims claims = null;        Contact contact = null;        if (token != null) {         //得到claims类            claims = TokenUtil.parseJWT(token);            cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(claims.getSubject());            contact = jsonObject.get("user", Contact.class);        }        return contact;    }

claims 中是解密后的token类,存储token中的全部信息

//解密token          claims = TokenUtil.parseJWT(token);        //得到用户的类型    String issuer = claims.getIssuer();        //得到登录的时间    Date issuedAt = claims.getIssuedAt();         //得到设置的登录id    String id = claims.getId();    //claims.getExpiration().getTime() > DateUtil.date().getTime() ,判断tokern是否过期            //得到存入token的对象              cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(claims.getSubject());            Contact  contact = jsonObject.get("user", Contact.class);

创建好的token会在页面中放置到请求头中,后台通过来拦截器来判断是否过期,若过期则拦截请求,成功则在响应头中返回新的token更新过期时间

package com.zeus.interceptor;import cn.hutool.core.date.DateUtil;import cn.hutool.json.JSON;import cn.hutool.json.JSONUtil;import com.zeus.utils.TokenUtil;import io.jsonwebtoken.Claims;import org.apache.commons.lang.StringUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.PrintWriter;import java.util.Map;import static com.zeus.constant.CommonConstants.EFFECTIVE_TIME;/** * 登陆拦截器 * * @author:fusheng * @date:2019/1/10 * @ver:1.0 **/public class LoginHandlerIntercepter implements HandlerInterceptor {    private static final Logger LOG = LoggerFactory.getLogger(LoginHandlerIntercepter.class);    /**     * token 校验     *     * @param httpServletRequest, httpServletResponse, o     * @return boolean     * @methodName preHandle     * @author fusheng     * @date 2019/1/3 0003     */    @Override    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {        Map<String, String[]> mapIn = httpServletRequest.getParameterMap();        JSON jsonObject = JSONUtil.parseObj(mapIn);        StringBuffer stringBuffer = httpServletRequest.getRequestURL();        LOG.info("httpServletRequest ,路径:" + stringBuffer + ",入参:" + JSONUtil.toJsonStr(jsonObject));        //校验APP的登陆状态,如果token 没有过期        LOG.info("come in preHandle");        String oldToken = httpServletRequest.getHeader("token");        LOG.info("token:" + oldToken);        /*刷新token,有效期延长至一个月*/        if (StringUtils.isNotBlank(oldToken)) {            Claims claims = null;            try {                claims = TokenUtil.parseJWT(oldToken);            } catch (Exception e) {                e.printStackTrace();                String str = "{\"code\":801,\"msg\":\"登陆失效,请重新登录\"}";                dealErrorReturn(httpServletRequest, httpServletResponse, str);                return false;            }            if (claims.getExpiration().getTime() > DateUtil.date().getTime()) {                String userId = claims.getId();                try {                    String newToken = TokenUtil.createJWT(claims.getId(), claims.getIssuer(), claims.getSubject(), EFFECTIVE_TIME);                    LOG.info("new TOKEN:{}", newToken);                    httpServletRequest.setAttribute("userId", userId);                    httpServletResponse.setHeader("token", newToken);                    LOG.info("flush token success ,{}", oldToken);                    return true;                } catch (Exception e) {                    e.printStackTrace();                    String str = "{\"code\":801,\"msg\":\"登陆失效,请重新登录\"}";                    dealErrorReturn(httpServletRequest, httpServletResponse, str);                    return false;                }            }        }        String str = "{\"code\":801,\"msg\":\"登陆失效,请重新登录\"}";        dealErrorReturn(httpServletRequest, httpServletResponse, str);        return false;    }    @Override    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {    }    @Override    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {    }    /**     * 返回错误信息给WEB     *     * @param httpServletRequest, httpServletResponse, obj     * @return void     * @methodName dealErrorReturn     * @author fusheng     * @date 2019/1/3 0003     */    public void dealErrorReturn(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object obj) {        String json = (String) obj;        PrintWriter writer = null;        httpServletResponse.setCharacterEncoding("UTF-8");        httpServletResponse.setContentType("application/json; charset=utf-8");        try {            writer = httpServletResponse.getWriter();            writer.print(json);        } catch (IOException ex) {            LOG.error("response error", ex);        } finally {            if (writer != null) {                writer.close();            }        }    }}

讲完了token ,再讲layui如何存储token,并在每次渲染时添加token到请求头中

form.on('submit(LAY-user-login-submit)', function (obj) {            //请求登入接口            admin.req({                //实际使用请改成服务端真实接口                url: '/userInfo/login',                method: 'POST',                data: obj.field,                done: function (res) {                    if (res.code === 0) {                        //请求成功后,写入 access_token                        layui.data(setter.tableName, {                            key: "token",                            value: res.data.token                        });                        //登入成功的提示与跳转                        layer.msg(res.msg, {                            offset: '15px',                            icon: 1,                            time: 1000                        }, function () {                            location.href ="index"                        });                    } else {                        layer.msg(res.msg, {                            offset: '15px',                            icon: 1,                            time: 1000                        });                    }                }            });        });

我们将返回的token信息存入layui本地存储的表中,在config.js中会配置表名,一般直接使用layui.setter.tableName 即可,

由于layui的table 是通过js渲染的,我们无法在js中对它进行设置请求头,而且每一个表格都要配置极为麻烦,但layui的数据表格是基于ajax请求的,所以我们选在在layui的module中手动修改table.js使得,每次请求是都会自动携带请求头

a.contentType && 0 == a.contentType.indexOf("application/json") && (d = JSON.stringify(d)), t.ajax({                type: a.method || "get",                url: a.url,                contentType: a.contentType,                data: d,                dataType: "json",                headers: {"token":layui.data(layui.setter.tableName)['token']},                success: function (t) {                    if(t.code==801){                        top.location.href = "index";                    }else {                        "function" == typeof a.parseData && (t = a.parseData(t) || t), t[n.statusName] != n.statusCode ? (i.renderForm(), i.layMain.html('<div class="' + f + '">' + (t[n.msgName] || "返回的数据不符合规范,正确的成功状态码 (" + n.statusName + ") 应为:" + n.statusCode) + "</div>")) : (i.renderData(t, e, t[n.countName]), o(), a.time = (new Date).getTime() - i.startTime + " ms"), i.setColsWidth(), "function" == typeof a.done && a.done(t, e, t[n.countName])                    }                },                error: function (e, t) {                    i.layMain.html('<div class="' + f + '">数据接口请求异常:' + t + "</div>"), i.renderForm(), i.setColsWidth()                },                complete: function( xhr,data ){                    layui.data(layui.setter.tableName, {                        key: "token",                        value: xhr.getResponseHeader("token")==null?layui.data(layui.setter.tableName)['token']:xhr.getResponseHeader("token")                    })                }            })

在table.js中找到这一代码,按上面的配置

headers: {"token":layui.data(layui.setter.tableName)['token']},这里是设置请求头的token,拿到登录成功后存储在表中的layui.data(layui.setter.tableName)['token'], 这样既可携带token很简单

同时我们需要更新token的过期时间,那么就要拿到新的token,并放入表中

  complete: function( xhr,data ){     layui.data(layui.setter.tableName, {key: "token",value: xhr.getResponseHeader("token")==null?layui.data(layui.setter.tableName)['token']:xhr.getResponseHeader("token") })}

使用ajax的complete方法拿到token,并覆盖表的旧token,如果为空则不覆盖

table讲完,来看看请求,layui中内置了jquery,可以使用var $ = layui,jquery, 来使用内置的ajax,那么我们也需要对ajax进行配置

pe.extend({        active: 0,        lastModified: {},        etag: {},        ajaxSettings: {            url: en,            type: "GET",            isLocal: Vt.test(tn[1]),            global: !0,            processData: !0,            async: !0,            headers: {"token":layui.data(layui.setter.tableName)['token']},            contentType: "application/x-www-form-urlencoded; charset=UTF-8",            accepts: {                "*": Zt,                text: "text/plain",                html: "text/html",                xml: "application/xml, text/xml",                json: "application/json, text/javascript"            },            contents: {xml: /\bxml\b/, html: /\bhtml/, json: /\bjson\b/},            responseFields: {xml: "responseXML", text: "responseText", json: "responseJSON"},            converters: {"* text": String, "text html": !0, "text json": pe.parseJSON, "text xml": pe.parseXML},            flatOptions: {url: !0, context: !0}        },

同样在l你引用的ayui.js或者layui.all.js中找到 ajaxSettings:配置一下即可。

更多layui知识请关注layui使用教程栏目。

以上就是layui登录后token问题详解的详细内容,更多请关注其它相关文章!


  • 上一条:
    layui框架分页设置详解
    下一条:
    layui模块化与非模块化的不同引用方式介绍
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 使用 Alpine.js 排序插件对元素进行排序(0个评论)
    • 在js中使用jszip + file-saver实现批量下载OSS文件功能示例(0个评论)
    • 在vue中实现父页面按钮显示子组件中的el-dialog效果(0个评论)
    • 使用mock-server实现模拟接口对接流程步骤(0个评论)
    • vue项目打包程序实现把项目打包成一个exe可执行程序(0个评论)
    • 近期文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • Laravel 11.15版本发布 - Eloquent Builder中添加的泛型(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-03
    • 2018-04
    • 2018-05
    • 2018-06
    • 2018-09
    • 2018-11
    • 2018-12
    • 2019-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2021-04
    • 2021-05
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客