朱纯树博客
VPS测评推荐网站
cloudacead cloudacead

layui登录后token问题解决

layui登录后token问题解决插图

 

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

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

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

首先引入jar包

io.jsonwebtokenjjwt0.7.0jackson-databindcom.fasterxml.jackson.core

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 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('
' + (t[n.msgName] || "返回的数据不符合规范,正确的成功状态码 (" + n.statusName + ") 应为:" + n.statusCode) + "
")) : (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('
数据接口请求异常:' + t + "
"), 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: /bxmlb/, html: /bhtml/, json: /bjsonb/},

            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登录后token问题解决

赞(0) 打赏
未经允许不得转载:VPS测评推荐网站 - 朱纯树博客 » layui登录后token问题解决

评论 25

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  1. #30

    Way cool! Some extremely valid points! I appreciate you penning this write-up and the rest of the website is really good.

  2. #29

    I’ve been exploring for a little bit for any high quality articles
    or blog posts in this sort of space . Exploring in Yahoo I eventually stumbled upon this site.
    Reading this information So i’m happy to
    exhibit that I’ve an incredibly excellent uncanny feeling I found out exactly what I needed.

    I most indubitably will make sure to don?t fail to remember this website and provides it a glance on a relentless basis.

  3. #28

    Do you mind if I quote a few of your posts as long as I provide credit and sources back to your blog?

    My blog is in the exact same area of interest as yours and my users would truly benefit from a lot of
    the information you provide here. Please let me know if this okay with you.
    Regards!

  4. #27

    Thanks , I’ve recently been looking for info about this subject for a long time
    and yours is the best I’ve found out so far. However, what
    concerning the conclusion? Are you sure concerning the source?

  5. #26

    Hello every one, here every one is sharing such know-how, so it’s pleasant to read
    this weblog, and I used to pay a visit this web site all the time.

    tinyurl.com3周前 (07-23)回复
  6. #25

    Quality content is the main to interest the users to go to see
    the web page, that’s what this website is providing.

    bit.ly3周前 (07-22)回复
  7. #24

    I couldn’t refrain from commenting. Exceptionally well written!

    tinyurl.com3周前 (07-22)回复
  8. #23

    Hi, its fastidious post concerning media print, we all know media is a fantastic source
    of data.

  9. #22

    What’s up, its fastidious article regarding media print,
    we all know media is a fantastic source of facts.

    tinyurl.com2个月前 (06-14)回复
  10. #21

    I was recommended this blog by my cousin. I’m not sure whether
    this post is written by him as no one else know such detailed about my
    difficulty. You’re amazing! Thanks!

    tinyurl.com2个月前 (06-12)回复