今天小編給大家分享的是layui登錄后token問題的解決方法,很多人都不太了解,今天小編為了讓大家更加了解,所以給大家總結(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)頁設(shè)計(jì)與制作、天涯企業(yè)網(wǎng)站模板建站服務(wù),十多年天涯做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。
layui是一個(gè)非常簡單且實(shí)用的后臺管理系統(tǒng)搭建框架,里面的插件豐富使用簡單,只需要在原有基礎(chǔ)上進(jìn)行修改即可,但是在數(shù)據(jù)處理方面略顯薄弱,內(nèi)置的jquery在實(shí)際過程中略顯不足,若是能添加內(nèi)置的mvc模式框架那就更好了
先介紹layui在登錄這一塊的使用,
登錄問題主要是在token的存儲(chǔ)調(diào)用上,先貼出后臺的創(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是否過期 //得到存入token的對象 cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(claims.getSubject()); Contact contact = jsonObject.get("user", Contact.class);
創(chuàng)建好的token會(huì)在頁面中放置到請求頭中,后臺通過來攔截器來判斷是否過期,若過期則攔截請求,成功則在響應(yīng)頭中返回新的token更新過期時(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 沒有過期 LOG.info("come in preHandle"); String oldToken = httpServletRequest.getHeader("token"); LOG.info("token:" + oldToken); /*刷新token,有效期延長至一個(gè)月*/ 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 { } /** * 返回錯(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到請求頭中
form.on('submit(LAY-user-login-submit)', function (obj) { //請求登入接口 admin.req({ //實(shí)際使用請改成服務(wù)端真實(shí)接口 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 }); //登入成功的提示與跳轉(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 是通過js渲染的,我們無法在js中對它進(jìn)行設(shè)置請求頭,而且每一個(gè)表格都要配置極為麻煩,但layui的數(shù)據(jù)表格是基于ajax請求的,所以我們選在在layui的module中手動(dòng)修改table.js使得,每次請求是都會(huì)自動(dò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ù)接口請求異常:' + 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è)置請求頭的token,拿到登錄成功后存儲(chǔ)在表中的layui.data(layui.setter.tableName)['token'], 這樣既可攜帶token很簡單
同時(shí)我們需要更新token的過期時(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講完,來看看請求,layui中內(nèi)置了jquery,可以使用var $ = layui,jquery, 來使用內(nèi)置的ajax,那么我們也需要對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問題的解決方法就分享到這里了,當(dāng)然并不止以上和大家分析的辦法,不過小編可以保證其準(zhǔn)確性是絕對沒問題的。希望以上內(nèi)容可以對大家有一定的參考價(jià)值,可以學(xué)以致用。如果喜歡本篇文章,不妨把它分享出去讓更多的人看到。
當(dāng)前標(biāo)題:layui登錄后token問題的解決方法
文章出自:http://www.rwnh.cn/article24/jjedje.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎ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)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)