搜尋
首頁web前端Layui教程layui登入後token問題詳解
layui登入後token問題詳解Dec 06, 2019 pm 05:04 PM
layuitoken

layui登入後token問題詳解

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(&#39;submit(LAY-user-login-submit)&#39;, function (obj) {
            //请求登入接口
            admin.req({
                //实际使用请改成服务端真实接口
                url: &#39;/userInfo/login&#39;,
                method: &#39;POST&#39;,
                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: &#39;15px&#39;,
                            icon: 1,
                            time: 1000
                        }, function () {
                            location.href ="index"

                        });
                    } else {
                        layer.msg(res.msg, {
                            offset: &#39;15px&#39;,
                            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)[&#39;token&#39;]},
                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(&#39;<div class="&#39; + f + &#39;">&#39; + (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(&#39;<div class="&#39; + f + &#39;">数据接口请求异常:&#39; + 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)[&#39;token&#39;]: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)[&#39;token&#39;]: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)[&#39;token&#39;]},
            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問題詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:博客园。如有侵權,請聯絡admin@php.cn刪除
2023最新layui视频教程推荐(建议收藏)2023最新layui视频教程推荐(建议收藏)Jul 19, 2021 pm 05:22 PM

以下为大家整理了前端UI框架 — layui的视频教程,不需要从迅雷、百度云之类的第三方网盘平台下载,全部在线免费观看。教程由浅入深,有前端基础的人就能学习,从安装到案例讲解,全面详细,帮助你更快更好的掌握layui框架!

如何利用Layui开发一个具有分页功能的数据展示页面如何利用Layui开发一个具有分页功能的数据展示页面Oct 24, 2023 pm 01:10 PM

如何利用Layui开发一个具有分页功能的数据展示页面Layui是一个轻量级的前端UI框架,提供了简洁美观的界面组件和丰富的交互体验。在开发中,我们经常会遇到需要展示大量数据并进行分页的情况。以下是一个利用Layui开发的具有分页功能的数据展示页面的示例。首先,我们需要引入Layui的相关文件和依赖。在html页面的&lt;head&gt;标签中加入以下代

如何利用Layui实现图片拖拽和缩放效果如何利用Layui实现图片拖拽和缩放效果Oct 24, 2023 am 09:16 AM

如何利用Layui实现图片拖拽和缩放效果在现代网页设计中,图片的交互效果成为增加网页活力和用户体验的重要手段。其中,图片拖拽和缩放效果是常见且受欢迎的交互方式之一。本文将介绍如何使用Layui框架实现图片拖拽和缩放效果,并提供具体的代码示例。一、引入Layui框架和相关依赖:首先,我们需要在HTML文件中引入Layui框架和相关依赖。可以通过以下代码示例引入

如何利用Layui实现图片轮播图功能如何利用Layui实现图片轮播图功能Oct 24, 2023 am 08:27 AM

如何利用Layui实现图片轮播图功能现如今,图片轮播图已经成为了网页设计中常见的元素之一。它可以使网页更加生动活泼,吸引用户的眼球,提升用户体验。在本文中,我们将介绍如何利用Layui框架来实现一个简单的图片轮播图功能。首先,我们需要在HTML页面中引入Layui的核心文件和样式文件:&lt;linkrel=&quot;stylesheet&quot;h

如何使用Layui开发一个支持图片放大缩小的相册功能如何使用Layui开发一个支持图片放大缩小的相册功能Oct 24, 2023 am 09:02 AM

如何使用Layui开发一个支持图片放大缩小的相册功能相册功能在现代的网页应用中非常常见,通过展示用户上传的图片,让用户能够方便地浏览和管理图片。为了提供更好的用户体验,一种常见的需求是支持图片的放大和缩小功能。本文章将介绍如何使用Layui框架开发一个支持图片放大缩小的相册功能,同时提供具体的代码示例。首先,确保您已经引入Layui框架的CSS和JS文件。您

如何使用Layui开发一个支持文件上传和下载的资源管理系统如何使用Layui开发一个支持文件上传和下载的资源管理系统Oct 24, 2023 am 09:19 AM

如何使用Layui开发一个支持文件上传和下载的资源管理系统引言:随着互联网的发展,数据资源的管理已经成为一项重要的任务。无论是企业内部的文档管理,还是个人的文件存储,都需要一个高效且易于使用的资源管理系统。Layui是一款轻量级的前端框架,具有简洁明了的设计以及丰富的组件库,非常适合用来进行资源管理系统的开发。本文将介绍如何使用Layui开发一个支持文

如何利用Layui实现图片反色和亮度调节功能如何利用Layui实现图片反色和亮度调节功能Oct 25, 2023 am 09:10 AM

如何利用Layui实现图片反色和亮度调节功能引言:在前端开发中,经常会遇到需要对图片进行特效处理的情况。本文将介绍如何利用Layui框架实现图片反色和亮度调节功能,并提供具体代码实例供参考。一、Layui简介:Layui是一款优秀的前端UI框架,具有简洁、美观、易用等特点。它提供了丰富的前端组件,让开发者能够轻松搭建出精美的网站。二、准备工作:在开始之前,我

如何使用Layui框架开发一个支持实时通讯的在线客服系统如何使用Layui框架开发一个支持实时通讯的在线客服系统Oct 25, 2023 am 08:47 AM

如何使用Layui框架开发一个支持实时通讯的在线客服系统概述:在线客服系统是现代企业提供与客户交流的重要渠道之一,而实时通讯是在线客服系统的关键技术之一。本文将介绍如何使用Layui框架开发一个支持实时通讯的在线客服系统,并提供具体的代码示例。一、准备工作安装Node.js:在开发环境中安装Node.js,并配置好相关环境。安装Layui:在项目中引入Lay

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境