Java中token的存儲和獲取實例代碼
1. 獲取token的工具類
問:為什么寫工具類呢???
答:因為我們不知道前端將token怎么存儲的,所以我們可以通過調(diào)用Token工具類來獲取token。Token工具類會檢查header、URL中的屬性值、以及Cookie等等?。?!
public class UserTokenUtil { public static String getToken(HttpServletRequest request, String tokenName) { String token = null; // 1. header token = request.getHeader(tokenName); if (StringUtils.isNotBlank(token)) { return token; } // 2. cookie Cookie[] cookies = request.getCookies(); if (cookies != null && cookies.length != 0) { for (Cookie cookie : cookies) { if (cookie != null && tokenName.equals(cookie.getName())) { token = cookie.getValue(); break; } } } if (StringUtils.isNotBlank(token)) { return token; } // 3. parameter token = request.getParameter(tokenName); return token; } }
2. header存儲token
2.1 前端存儲token
第一步安裝:js-cookie
npm install --save js-cookie
第二步引入:(這里以vue開發(fā)為例,在main.js中引入?。?/p>
// 全局應用Cookie import Cookie from 'js-cookie' Vue.prototype.$Cookie = Cookie
第三步:前端訪問后端,得到token后進行存儲。
// 向后端發(fā)送登錄請求 this.axios({ method: "post", headers: { // 測試header保存數(shù)據(jù) "hahah": "text_header_save_Data" }, url: "http://" + that.$store.state.host + "/zm-task/login/goLogin", data: { "loginNumber": that.ruleForm.user, "password": that.ruleForm.pass } }).then(function (res) { // console.log(res.data); //根據(jù)后端返回的狀態(tài)查看賬號是否正確 if (res.data.code == 0) { // =============== cookie的操作 ================ // 博文: https://blog.csdn.net/qq_16828495/article/details/120783389 // 保存token that.$Cookie.set("token", res.data.data.token); //登錄成功后跳轉(zhuǎn)到后臺的個人信息界面 that.$message.success("登錄成功!"); that.$router.push({path: "/userInfo"}); } else { that.$message.error(res.data.message); } }) .catch(err => { // 后端如果出現(xiàn)異常,前端會報401錯誤。 這里捕獲401錯誤。 //console.log(err.response.data) if (err.response != null) { this.$message.error(err.response.data.message); } else { this.$message.error("未知異常"); } })
2.2 訪問攜帶token
axios({ method: "get", headers: { // 傳輸token用于驗證當前登錄用戶 "token": that.$Cookie.get("token"), }, url: "http://" + that.$store.state.host + "/zm-task/login/updateEmail", params:{ // 需要修改的郵箱屬性 "email": formName.email } }).then(res => { // 直接顯示后端傳來的信息 that.$message.success(res.data.message); }).catch(err => { // 后端如果出現(xiàn)異常,前端會報401錯誤。 這里捕獲401錯誤。 if (err.response != null) { this.$message.error(err.response.data.message); } else { this.$message.error("未知異常"); } })
2.3 后端獲取token并進行驗證(攔截器中進行驗證)
@Slf4j public class UserLoginAuthInterceptor implements HandlerInterceptor { /** * * @param request : 請求(通過請求獲取token登陸憑證) * @param response : 返回給前端的響應 * @param handler : 該參數(shù)中包含了對應方法的信息。比如:方法中的參數(shù)類型、參數(shù)的注解、方法的注解等信息。 * @return * @throws Exception : 向上拋出異常 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 排除資源請求 if (!(handler instanceof HandlerMethod)) { return true; } // 通過handler獲取方法上面的Login注解 HandlerMethod handlerMethod = (HandlerMethod) handler; Login login = handlerMethod.getMethod().getAnnotation(Login.class); //說明方法上面沒有Login注解 if (login == null){ return true; } // 有Login注解,但是Login的屬性值為false if (Boolean.FALSE.equals(login.loginRequired())){ return true; } // 獲取請求頭中的token請求 String token = request.getHeader("token"); // 根據(jù)token獲取登陸的用戶信息(登陸賬號, 登陸ip, 用戶權限0、1、2) UserLoginModel userLoginModel = JWTUtil.tokenToUser(token, request); // 獲取當前請求的ip地址?。?! (公網(wǎng)才有效果) String ipAddr = IPUtil.getIpAddr(request); if (StringUtils.isBlank(ipAddr)){ throw new BizException(ServerEnum.IP_GET_ERROR); } if (userLoginModel == null){ //todo redis保存ip地址,防止被爆刷接口 throw new BizException(ServerEnum.LOGIN_ERROR); } // 這里只有線上測試才能有效果,非線上測試無效果! (ipAddr公網(wǎng)才能獲取準確的IPv4) if (!ipAddr.equals(userLoginModel.getIP())){ // 登陸IP 與 請求IP不相同,所以重新進行登陸 log.error("登陸ip:{}, 請求ip:{}", userLoginModel.getIP(), ipAddr); //todo redis保存ip地址,防止被爆刷接口 throw new BizException(ServerEnum.LOGIN_ERROR); } //使用ThreadLocal保存用戶信息 UserLoginInfoThreadLocalUtil.set(userLoginModel); return true; } /** * 在整個請求處理完畢后進行回調(diào),也就是說視圖渲染完畢或者調(diào)用方已經(jīng)拿到響應。 * @param request * @param response * @param handler * @param ex * @throws Exception */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { //防止內(nèi)存泄漏 UserLoginInfoThreadLocalUtil.clear(); } }
3. URL中的屬性值
以這個地址為例:https://editor.csdn.net/md?articleId=125379150&name=Thomas
當進行Get
或者Post
請求的時候,在url后面添加參數(shù)便可以?。。?/p>
public class UserTokenUtil { public static String getToken(HttpServletRequest request, String tokenName) { String articleId = null; String name = null; // articleId = 125379150 articleId = request.getParameter(articleId); // name = Thomas name = request.getParameter(name); return articleId + " " + name; } }
4. Cookie
4.1 控制器代碼
@RestController @RequestMapping("/cookie") public class CookieTestController { // http://localhost:8080/cookie/login/tokentoken?id=13213 @GetMapping("/login/{token}") public void getLogin(HttpServletRequest request, HttpServletResponse response) throws IOException { //設置請求編碼格式 request.setCharacterEncoding("UTF-8"); //設置響應編碼格式 response.setCharacterEncoding("UTF-8"); //設置數(shù)據(jù)返回的類型 response.setContentType("text/json"); // 獲取請求信息(參數(shù)id對應的值) Integer id = Integer.valueOf(request.getParameter("id")); // 原本想獲取請求url中的值,但是無法通過request獲取?。。?! String token = request.getPathInfo(); System.out.println(request.getMethod()); // GET System.out.println(request.getRequestURI()); // /cookie/login/tokentoken Enumeration<String> parameterNames = request.getParameterNames(); while (parameterNames.hasMoreElements()){ // id (說明只能獲取路徑?后面的參數(shù),不能獲取包含在路徑中的參數(shù)?。?!) System.out.println(parameterNames.nextElement()); } // 添加cookie信息 Cookie c1 = new Cookie("token_cxp_zm", "chsdiufvbndsufyvbnduh"); Cookie c2 = new Cookie("cxp-love_zm", "hahahahaha---cxp---love=---zm"); response.addCookie(c1); response.addCookie(c2); PrintWriter out = response.getWriter(); out.write("XXXXXXX" + id + " == " + token); out.flush();//刷新該流的緩沖 out.close();//關閉流 } // http://localhost:8080/cookie/login/getCookie @GetMapping("/login/getCookie") public void getCookies(HttpServletRequest request, HttpServletResponse response) throws IOException { //設置數(shù)據(jù)返回的類型 response.setContentType("text/json"); //設置請求編碼格式 request.setCharacterEncoding("UTF-8"); //設置響應編碼格式 response.setCharacterEncoding("UTF-8"); String State = "fail"; //獲取Cookie信息數(shù)組 Cookie[] cks = request.getCookies(); if (cks != null){ for(Cookie cookie : cks){ System.out.println(cookie.getName() + "=" + cookie.getValue()); } } PrintWriter out=response.getWriter(); out.write("測試獲取Cookie"); out.flush();//刷新該流的緩沖 out.close();//關閉流 } }
4.2 測試 向Cookie中插入key - value值?。?!
之后的Get或者Post請求,不需要我們主動去插入cookie,請求會自動攜帶cookie進行訪問!?。?/p>
講解完畢?。?!
注意:
問題:因為后端去設置Cookie,會涉及跨域,但是cookie是不能跨域的。這就造成了頁面跳轉(zhuǎn)時請求頭帶不上cookie中的token。這時只要把Domain設置成.+一級域名那么就能解決cookie跨域的問題了。
Token的使用(兩種方式):
1、 直接返回token字符,讓前端同學進行存儲(Cookie、localStorage、SessionStorage),請求時候手動去攜帶token??!
2、 后端同學設置cookie的時候,注意跨域問題即可!
總結
到此這篇關于Java中token的存儲和獲取的文章就介紹到這了,更多相關Java存儲和獲取token內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java數(shù)組隊列及環(huán)形數(shù)組隊列超詳細講解
隊列是一個有序列表,可以用數(shù)組和鏈表來實現(xiàn),隊列有一個原則。即:先存入隊列的數(shù)據(jù)要先取出,后存入的要后取出,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧2022-09-09使用SpringMVC的@Validated注解驗證的實現(xiàn)
這篇文章主要介紹了使用SpringMVC的@Validated注解驗證的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-08-08Springboot集成mybatis實現(xiàn)多數(shù)據(jù)源配置詳解流程
在日常開發(fā)中,若遇到多個數(shù)據(jù)源的需求,怎么辦呢?通過springboot集成mybatis實現(xiàn)多數(shù)據(jù)源配置,簡單嘗試一下,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-06-06

Spring擴展BeanFactoryPostProcessor使用技巧詳解