layui登錄后token問(wèn)題的解決方法

今天小編給大家分享的是layui登錄后token問(wèn)題的解決方法,很多人都不太了解,今天小編為了讓大家更加了解,所以給大家總結(jié)了以下內(nèi)容,一起往下看吧。一定會(huì)有所收獲的哦。

成都創(chuàng)新互聯(lián)公司專業(yè)為企業(yè)提供天涯網(wǎng)站建設(shè)、天涯做網(wǎng)站、天涯網(wǎng)站設(shè)計(jì)、天涯網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)與制作、天涯企業(yè)網(wǎng)站模板建站服務(wù),十多年天涯做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。

layui登錄后token問(wèn)題的解決方法

layui是一個(gè)非常簡(jiǎn)單且實(shí)用的后臺(tái)管理系統(tǒng)搭建框架,里面的插件豐富使用簡(jiǎn)單,只需要在原有基礎(chǔ)上進(jìn)行修改即可,但是在數(shù)據(jù)處理方面略顯薄弱,內(nèi)置的jquery在實(shí)際過(guò)程中略顯不足,若是能添加內(nèi)置的mvc模式框架那就更好了

先介紹layui在登錄這一塊的使用,

登錄問(wèn)題主要是在token的存儲(chǔ)調(diào)用上,先貼出后臺(tái)的創(chuàng)建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 ,可以自定義秘鑰,并存儲(chǔ)登錄信息

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);

    /**
     * 創(chuàng)建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類,存儲(chǔ)token中的全部信息

//解密token          
claims = TokenUtil.parseJWT(token);        //得到用戶的類型
    String issuer = claims.getIssuer();        //得到登錄的時(shí)間
    Date issuedAt = claims.getIssuedAt();         //得到設(shè)置的登錄id
    String id = claims.getId();    //claims.getExpiration().getTime() > DateUtil.date().getTime() ,判斷tokern是否過(guò)期        
    //得到存入token的對(duì)象          
    cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(claims.getSubject());        
    Contact  contact = jsonObject.get("user", Contact.class);

創(chuàng)建好的token會(huì)在頁(yè)面中放置到請(qǐng)求頭中,后臺(tái)通過(guò)來(lái)攔截器來(lái)判斷是否過(guò)期,若過(guò)期則攔截請(qǐng)求,成功則在響應(yīng)頭中返回新的token更新過(guò)期時(shí)間

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 校驗(yàn)
     *
     * @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 + ",入?yún)?" + JSONUtil.toJsonStr(jsonObject));

        //校驗(yàn)APP的登陸狀態(tài),如果token 沒(méi)有過(guò)期
        LOG.info("come in preHandle");
        String oldToken = httpServletRequest.getHeader("token");
        LOG.info("token:" + oldToken);
        /*刷新token,有效期延長(zhǎng)至一個(gè)月*/
        if (StringUtils.isNotBlank(oldToken)) {
            Claims claims = null;
            try {
                claims = TokenUtil.parseJWT(oldToken);
            } catch (Exception e) {
                e.printStackTrace();
                String str = "{\"code\":801,\"msg\":\"登陸失效,請(qǐng)重新登錄\"}";
                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\":\"登陸失效,請(qǐng)重新登錄\"}";
                    dealErrorReturn(httpServletRequest, httpServletResponse, str);
                    return false;
                }
            }
        }
        String str = "{\"code\":801,\"msg\":\"登陸失效,請(qǐng)重新登錄\"}";
        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 {
    }

    /**
     * 返回錯(cuò)誤信息給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如何存儲(chǔ)token,并在每次渲染時(shí)添加token到請(qǐng)求頭中

form.on('submit(LAY-user-login-submit)', function (obj) {
            //請(qǐng)求登入接口
            admin.req({
                //實(shí)際使用請(qǐng)改成服務(wù)端真實(shí)接口
                url: '/userInfo/login',
                method: 'POST',
                data: obj.field,
                done: function (res) {
                    if (res.code === 0) {
                        //請(qǐng)求成功后,寫入 access_token
                        layui.data(setter.tableName, {
                            key: "token",
                            value: res.data.token
                        });
                        //登入成功的提示與跳轉(zhuǎn)
                        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本地存儲(chǔ)的表中,在config.js中會(huì)配置表名,一般直接使用layui.setter.tableName 即可,

由于layui的table 是通過(guò)js渲染的,我們無(wú)法在js中對(duì)它進(jìn)行設(shè)置請(qǐng)求頭,而且每一個(gè)表格都要配置極為麻煩,但layui的數(shù)據(jù)表格是基于ajax請(qǐng)求的,所以我們選在在layui的module中手動(dòng)修改table.js使得,每次請(qǐng)求是都會(huì)自動(dòng)攜帶請(qǐng)求頭

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] || "返回的數(shù)據(jù)不符合規(guī)范,正確的成功狀態(tài)碼 (" + n.statusName + ") 應(yīng)為:" + 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 + '">數(shù)據(jù)接口請(qǐng)求異常:' + 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']},這里是設(shè)置請(qǐng)求頭的token,拿到登錄成功后存儲(chǔ)在表中的layui.data(layui.setter.tableName)['token'], 這樣既可攜帶token很簡(jiǎn)單

同時(shí)我們需要更新token的過(guò)期時(shí)間,那么就要拿到新的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講完,來(lái)看看請(qǐng)求,layui中內(nèi)置了jquery,可以使用var $ = layui,jquery, 來(lái)使用內(nèi)置的ajax,那么我們也需要對(duì)ajax進(jìn)行配置

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:配置一下即可。

關(guān)于layui登錄后token問(wèn)題的解決方法就分享到這里了,當(dāng)然并不止以上和大家分析的辦法,不過(guò)小編可以保證其準(zhǔn)確性是絕對(duì)沒(méi)問(wèn)題的。希望以上內(nèi)容可以對(duì)大家有一定的參考價(jià)值,可以學(xué)以致用。如果喜歡本篇文章,不妨把它分享出去讓更多的人看到。

當(dāng)前標(biāo)題:layui登錄后token問(wèn)題的解決方法
文章出自:http://bm7419.com/article24/jjedje.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站營(yíng)銷、品牌網(wǎng)站設(shè)計(jì)虛擬主機(jī)、企業(yè)網(wǎng)站制作用戶體驗(yàn)、外貿(mào)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站建設(shè)