1. 程式人生 > >Spring Boot實戰之Filter實現使用JWT進行介面認證 jwt(json web token) 使用者傳送按照約定,向服務端傳送 Header、Payload 和 Signature,

Spring Boot實戰之Filter實現使用JWT進行介面認證 jwt(json web token) 使用者傳送按照約定,向服務端傳送 Header、Payload 和 Signature,

Spring Boot實戰之Filter實現使用JWT進行介面認證

jwt(json web token)

使用者傳送按照約定,向服務端傳送 Header、Payload 和 Signature,幷包含認證資訊(密碼),驗證通過後服務端返回一個token,之後使用者使用該token作為登入憑證,適合於移動端和api

jwt使用流程


本文示例接上面幾篇文章中的程式碼進行編寫,請閱讀本文的同時可以參考前面幾篇文章

1、新增依賴庫jjwt,本文中構造jwt及解析jwt都使用了jjwt庫

  1. <dependency>
  2.     <groupId>io.jsonwebtoken
    </groupId>
  3.     <artifactId>jjwt</artifactId>
  4.     <version>0.6.0</version>
  5. </dependency>


2、新增登入獲取token時,所需要的認證資訊類LoginPara.java

  1. package com.xiaofangtech.sunt.jwt;  
  2. publicclass LoginPara {  
  3.     private String clientId;  
  4.     private String userName;  
  5.     private String password;  
  6.     private String captchaCode;  
  7.     private String captchaValue;  
  8.     public String getClientId() {  
  9.         return clientId;  
  10.     }  
  11.     publicvoid setClientId(String clientId) {  
  12.         this.clientId = clientId;  
  13.     }  
  14.     public String getUserName() {  
  15.         return userName;  
  16.     }  
  17.     public
    void setUserName(String userName) {  
  18.         this.userName = userName;  
  19.     }  
  20.     public String getPassword() {  
  21.         return password;  
  22.     }  
  23.     publicvoid setPassword(String password) {  
  24.         this.password = password;  
  25.     }  
  26.     public String getCaptchaCode() {  
  27.         return captchaCode;  
  28.     }  
  29.     publicvoid setCaptchaCode(String captchaCode) {  
  30.         this.captchaCode = captchaCode;  
  31.     }  
  32.     public String getCaptchaValue() {  
  33.         return captchaValue;  
  34.     }  
  35.     publicvoid setCaptchaValue(String captchaValue) {  
  36.         this.captchaValue = captchaValue;  
  37.     }  
  38. }  
3、新增構造jwt及解析jwt的幫助類JwtHelper.java
  1. package com.xiaofangtech.sunt.jwt;  
  2. import java.security.Key;  
  3. import java.util.Date;  
  4. import javax.crypto.spec.SecretKeySpec;  
  5. import javax.xml.bind.DatatypeConverter;  
  6. import io.jsonwebtoken.Claims;  
  7. import io.jsonwebtoken.JwtBuilder;  
  8. import io.jsonwebtoken.Jwts;  
  9. import io.jsonwebtoken.SignatureAlgorithm;  
  10. publicclass JwtHelper {  
  11.     publicstatic Claims parseJWT(String jsonWebToken, String base64Security){  
  12.         try
  13.         {  
  14.             Claims claims = Jwts.parser()  
  15.                        .setSigningKey(DatatypeConverter.parseBase64Binary(base64Security))  
  16.                        .parseClaimsJws(jsonWebToken).getBody();  
  17.             return claims;  
  18.         }  
  19.         catch(Exception ex)  
  20.         {  
  21.             returnnull;  
  22.         }  
  23.     }  
  24.     publicstatic String createJWT(String name, String userId, String role,   
  25.             String audience, String issuer, long TTLMillis, String base64Security)   
  26.     {  
  27.         SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;  
  28.         long nowMillis = System.currentTimeMillis();  
  29.         Date now = new Date(nowMillis);  
  30.         //生成簽名金鑰
  31.         byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(base64Security);  
  32.         Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());  
  33.           //新增構成JWT的引數
  34.         JwtBuilder builder = Jwts.builder().setHeaderParam("typ""JWT")  
  35.                                         .claim("role", role)  
  36.                                         .claim("unique_name", name)  
  37.                                         .claim("userid", userId)  
  38.                                         .setIssuer(issuer)  
  39.                                         .setAudience(audience)  
  40.                                         .signWith(signatureAlgorithm, signingKey);  
  41.          //新增Token過期時間
  42.         if (TTLMillis >= 0) {  
  43.             long expMillis = nowMillis + TTLMillis;  
  44.             Date exp = new Date(expMillis);  
  45.             builder.setExpiration(exp).setNotBefore(now);  
  46.         }  
  47.          //生成JWT
  48.         return builder.compact();  
  49.     }   
  50. }  


4、新增token返回結果類AccessToken.java

  1. package com.xiaofangtech.sunt.jwt;  
  2. publicclass AccessToken {  
  3.     private String access_token;  
  4.     private String token_type;  
  5.     privatelong expires_in;  
  6.     public String getAccess_token() {  
  7.         return access_token;  
  8.     }  
  9.     publicvoid setAccess_token(String access_token) {  
  10.         this.access_token = access_token;  
  11.     }  
  12.     public String getToken_type() {  
  13.         return token_type;  
  14.     }  
  15.     publicvoid setToken_type(String token_type) {  
  16.         this.token_type = token_type;  
  17.     }  
  18.     publiclong getExpires_in() {  
  19.         return expires_in;  
  20.     }  
  21.     publicvoid setExpires_in(long expires_in) {  
  22.         this.expires_in = expires_in;  
  23.     }  
  24. }  
5、新增獲取token的介面,通過傳入使用者認證資訊(使用者名稱、密碼)進行認證獲取
  1. package com.xiaofangtech.sunt.jwt;  
  2. import org.springframework.beans.factory.annotation.Autowired;  
  3. import org.springframework.web.bind.annotation.RequestBody;  
  4. import org.springframework.web.bind.annotation.RequestMapping;  
  5. import org.springframework.web.bind.annotation.RestController;  
  6. import com.xiaofangtech.sunt.bean.UserInfo;  
  7. import com.xiaofangtech.sunt.repository.UserInfoRepository;  
  8. import com.xiaofangtech.sunt.utils.MyUtils;  
  9. import com.xiaofangtech.sunt.utils.ResultMsg;  
  10. import com.xiaofangtech.sunt.utils.ResultStatusCode;  
  11. @RestController
  12. publicclass JsonWebToken {  
  13.     @Autowired
  14.     private UserInfoRepository userRepositoy;  
  15.     @Autowired
  16.     private Audience audienceEntity;  
  17.     @RequestMapping("oauth/token")  
  18.     public Object getAccessToken(@RequestBody LoginPara loginPara)  
  19.     {  
  20.         ResultMsg resultMsg;  
  21.         try
  22.         {  
  23.             if(loginPara.getClientId() == null
  24.                     || (loginPara.getClientId().compareTo(audienceEntity.getClientId()) != 0))  
  25.             {  
  26.                 resultMsg = new ResultMsg(ResultStatusCode.INVALID_CLIENTID.getErrcode(),   
  27.                         ResultStatusCode.INVALID_CLIENTID.getErrmsg(), null);  
  28.                 return resultMsg;  
  29.             }  
  30.             //驗證碼校驗在後面章節新增
  31.             //驗證使用者名稱密碼
  32.             UserInfo user = userRepositoy.findUserInfoByName(loginPara.getUserName());  
  33.             if (user == null)  
  34.             {  
  35.                 resultMsg = new ResultMsg(ResultStatusCode.INVALID_PASSWORD.getErrcode(),  
  36.                         ResultStatusCode.INVALID_PASSWORD.getErrmsg(), null);  
  37.                 return resultMsg;  
  38.             }  
  39.             else
  40.             {  
  41.                 String md5Password = MyUtils.getMD5(loginPara.getPassword()+user.getSalt());  
  42.                 if (md5Password.compareTo(user.getPassword()) != 0)  
  43.                 {  
  44.                     resultMsg = new ResultMsg(ResultStatusCode.INVALID_PASSWORD.getErrcode(),  
  45.                             ResultStatusCode.INVALID_PASSWORD.getErrmsg(), null);  
  46.                     return resultMsg;  
  47.                 }  
  48.             }  
  49.             //拼裝accessToken
  50.             String accessToken = JwtHelper.createJWT(loginPara.getUserName(), String.valueOf(user.getName()),  
  51.                     user.getRole(), audienceEntity.getClientId(), audienceEntity.getName(),  
  52.                     audienceEntity.getExpiresSecond() * 1000, audienceEntity.getBase64Secret());  
  53.             //返回accessToken
  54.             AccessToken accessTokenEntity = new AccessToken();  
  55.             accessTokenEntity.setAccess_token(accessToken);  
  56.             accessTokenEntity.setExpires_in(audienceEntity.getExpiresSecond());  
  57.             accessTokenEntity.setToken_type("bearer");  
  58.             resultMsg = new ResultMsg(ResultStatusCode.OK.getErrcode(),   
  59.                     ResultStatusCode.OK.getErrmsg(), accessTokenEntity);  
  60.             return resultMsg;  
  61.         }  
  62.         catch(Exception ex)  
  63.         {  
  64.             resultMsg = new ResultMsg(ResultStatusCode.SYSTEM_ERR.getErrcode(),   
  65.                     ResultStatusCode.SYSTEM_ERR.getErrmsg(), null);  
  66.             return resultMsg;  
  67.         }  
  68.     }  
  69. }  


6、新增使用jwt認證的filter
  1. package com.xiaofangtech.sunt.filter;  
  2. import java.io.IOException;  
  3. import javax.servlet.Filter;  
  4. import javax.servlet.FilterChain;  
  5. import javax.servlet.FilterConfig;  
  6. import javax.servlet.ServletException;  
  7. import javax.servlet.ServletRequest;  
  8. import javax.servlet.ServletResponse;  
  9. import javax.servlet.http.HttpServletRequest;  
  10. import javax.servlet.http.HttpServletResponse;  
  11. import org.springframework.beans.factory.annotation.Autowired;  
  12. import org.springframework.web.context.support.SpringBeanAutowiringSupport;  
  13. import com.fasterxml.jackson.databind.ObjectMapper;  
  14. import com.xiaofangtech.sunt.jwt.Audience;  
  15. import com.xiaofangtech.sunt.jwt.JwtHelper;  
  16. import com.xiaofangtech.sunt.utils.ResultMsg;  
  17. import com.xiaofangtech.sunt.utils.ResultStatusCode;  
  18. publicclass HTTPBearerAuthorizeAttribute implements Filter{  
  19.     @Autowired
  20.     private Audience audienceEntity;  
  21.     @Override
  22.     publicvoid init(FilterConfig filterConfig) throws ServletException {  
  23.         // TODO Auto-generated method stub
  24.         SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this,  
  25.                 filterConfig.getServletContext());  
  26.     }  
  27.     @Override
  28.     publicvoid doFilter(ServletRequest request, ServletResponse response, FilterChain chain)  
  29.             throws IOException, ServletException {  
  30.         // TODO Auto-generated method stub
  31.         ResultMsg resultMsg;  
  32.         HttpServletRequest httpRequest = (HttpServletRequest)request;  
  33.         String auth = httpRequest.getHeader("Authorization");  
  34.         if ((auth != null) && (auth.length() > 7))  
  35.         {  
  36.             String HeadStr = auth.substring(06).toLowerCase();  
  37.             if (HeadStr.compareTo("bearer") == 0)  
  38.             {  
  39.                 auth = auth.substring(7, auth.length());   
  40.                 if (JwtHelper.parseJWT(auth, audienceEntity.getBase64Secret()) != null)  
  41.                 {  
  42.                     chain.doFilter(request, response);  
  43.                     return;  
  44.                 }  
  45.             }  
  46.         }  
  47.         HttpServletResponse httpResponse = (HttpServletResponse) response;  
  48.         httpResponse.setCharacterEncoding("UTF-8");    
  49.         httpResponse.setContentType("application/json; charset=utf-8");   
  50.         httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);  
  51.         ObjectMapper mapper = new ObjectMapper();  
  52.         resultMsg = new ResultMsg(ResultStatusCode.INVALID_TOKEN.getErrcode(), ResultStatusCode.INVALID_TOKEN.getErrmsg(), null);  
  53.         httpResponse.getWriter().write(mapper.writeValueAsString(resultMsg));  
  54.         return;  
  55.     }  
  56.     @Override
  57.     publicvoid destroy() {  
  58.         // TODO Auto-generated method stub
  59.     }  
  60. }  
7、在入口處註冊filter
  1. package com.xiaofangtech.sunt;  
  2. import java.util.ArrayList;  
  3. import java.util.List;  
  4. import org.springframework.boot.SpringApplication;  
  5. import org.springframework.boot.autoconfigure.SpringBootApplication;  
  6. import org.springframework.boot.context.embedded.FilterRegistrationBean;  
  7. import org.springframework.boot.context.properties.EnableConfigurationProperties;  
  8. import org.springframework.context.annotation.Bean;  
  9. import com.xiaofangtech.sunt.filter.HTTPBasicAuthorizeAttribute;  
  10. import com.xiaofangtech.sunt.filter.HTTPBearerAuthorizeAttribute;  
  11. import com.xiaofangtech.sunt.jwt.Audience;  
  12. @SpringBootApplication
  13. @EnableConfigurationProperties(Audience.class)  
  14. publicclass SpringRestApplication {  
  15.     publicstaticvoid main(String[] args) {  
  16.         SpringApplication.run(SpringRestApplication.class, args);  
  17.     }  
  18.     @Bean
  19.     public FilterRegistrationBean  basicFilterRegistrationBean() {  
  20.         FilterRegistrationBean registrationBean = new FilterRegistrationBean();  
  21.         HTTPBasicAuthorizeAttribute httpBasicFilter = new HTTPBasicAuthorizeAttribute();  
  22.         registrationBean.setFilter(httpBasicFilter);  
  23.         List<String> urlPatterns = new ArrayList<String>();  
  24.         urlPatterns.add("/user/getuser");  
  25.         registrationBean.setUrlPatterns(urlPatterns);  
  26.         return registrationBean;  
  27.     }  
  28.     @Bean
  29.     public FilterRegistrationBean jwtFilterRegistrationBean(){  
  30.         FilterRegistrationBean registrationBean = new FilterRegistrationBean();  
  31.         HTTPBearerAuthorizeAttribute httpBearerFilter = new HTTPBearerAuthorizeAttribute();  
  32.         registrationBean.setFilter(httpBearerFilter);  
  33.         List<String> urlPatterns = new ArrayList<String>();  
  34.         urlPatterns.add("/user/getusers");  
  35.         registrationBean.setUrlPatterns(urlPatterns);  
  36.         return registrationBean;  
  37.     }  
  38. }  

8、新增獲取md5的方法類MyUtils
  1. package com.xiaofangtech.sunt.utils;  
  2. import java.security.MessageDigest;  
  3. publicclass MyUtils {  
  4.     publicstatic String getMD5(String inStr) {  
  5.         MessageDigest md5 = null;  
  6.         try {  
  7.             md5 = MessageDigest.getInstance("MD5");  
  8.         } catch (Exception e) {  
  9.             e.printStackTrace();  
  10.             return"";  
  11.         }  
  12.         char[] charArray = inStr.toCharArray();  
  13.         byte[] byteArray = newbyte[charArray.length];  
  14.         for (int i = 0; i < charArray.length; i++)  
  15.             byteArray[i] = (byte) charArray[i];  
  16.         byte[] md5Bytes = md5.digest(byteArray);  
  17.         StringBuffer hexValue = new StringBuffer();  
  18.         for (int i = 0; i < md5Bytes.length; i++) {  
  19.             int val = ((int) md5Bytes[i]) & 0xff;  
  20.             if (val < 16)  
  21.                 hexValue.append("0");  
  22.             hexValue.append(Integer.toHexString(val));  
  23.         }  
  24.         return hexValue.toString();  
  25.     }  
  26. }  

9、在返回資訊類中補充新增錯誤碼

  1.        INVALID_CLIENTID(30003"Invalid clientid"),  
  2. INVALID_PASSWORD(30004"User name or password is incorrect"),  
  3. INVALID_CAPTCHA(30005"Invalid captcha or captcha overdue"),  
  4. INVALID_TOKEN(30006"Invalid token");  


10、程式碼中涉及的Audience類,在上一篇文章中定義,本文不再重複說明

11、程式碼整體結構


12、測試

1) 獲取token,傳入使用者認證資訊



    認證通過返回token資訊


2) 使用上面獲取的token進行介面呼叫

     未使用token,獲取token錯誤,或者token過期時


    使用正確的token時

相關推薦

Spring Boot實戰Filter實現使用JWT進行介面認證 jwt(json web token) 使用者傳送按照約定服務傳送 HeaderPayload Signature

Spring Boot實戰之Filter實現使用JWT進行介面認證 jwt(json web token) 使用者傳送按照約定,向服務端傳送 Header、Payload 和 Signature,幷包含認證資訊(密碼),驗證通過後服務端返回一個token,之後使用者使用該

Spring Boot實戰Filter實現使用JWT進行介面認證

jwt(json web token) 使用者傳送按照約定,向服務端傳送 Header、Payload 和 Signature,幷包含認證資訊(密碼),驗證通過後服務端返回一個token,之後使用者使用該token作為登入憑證,適合於移動端和api j

Spring Boot實戰逐行釋義HelloWorld

runtime ica can pri source 訪問 exclude 這樣的 gradle 一、前言    研究Spring boot也有一小段時間了,最近會將研究東西整理一下給大家分享,大概會有10~20篇左右的博客,整個系列會以一個簡單的博客系統作為基礎,因為光

Spring Boot實戰數據庫操作

應該 element face 插入 sele run 方式 不同 pan   上篇文章中已經通過一個簡單的HelloWorld程序講解了Spring boot的基本原理和使用。本文主要講解如何通過spring boot來訪問數據庫,本文會演示三種方式來訪問數據庫,第一種是

Spring Boot實戰匯出excel並上傳存入Azure Storage

Spring Boot實戰之匯出excel 本文使用Apache POI實現excel文件的匯出。 實現從資料庫讀取資料——生成excel——上傳到AzureStorage的流程 資料庫操作,及檔案上傳AzureStorage的流程可以參考之前的文章 http://blog

spring boot實戰shiro session過期時間

在spring boot內,設定session過期時間只需在application.properties內新增server.session.timeout配置即可。在整合shiro時發現,server.session.timeout設定為7200,但未到2小時就

Spring Boot實戰匯出excel檔案。

Spring Boot實戰之匯出excel本文使用Apache POI實現excel文件的匯出。 實現從資料庫讀取資料——生成excel——上傳到AzureStorage的流程資料庫操作,及檔案上傳AzureStorage的流程可以參考之前的文章http://blog.csdn.net/sun_t89/art

spring boot實戰日期處理

web開發中經常需要對日期進行操作,如字串日期轉long,long型轉字串,日期計算等,提取一個日期處理工具類,提供常見的日期操作可以讓開發更輕鬆一些。 毫秒(long)轉字串日期 對long型時間進行格式化在web開發中是很經常出現的一個操作,這裡主要

spring boot實戰CSRF(跨站請求偽造)

CSRF(Cross-site request forgery)跨站請求偽造,也被稱為“One Click Attack”或者Session Riding,通常縮寫為CSRF或者XSRF,是一種對網站的惡意利用。攻擊通過在授權使用者訪問的頁面中包含連結或者

利用socket技術實現用java實現客戶服務傳送檔案伺服器接收檔案並給出一個響應。

通訊是網路程式設計中重要的組成部分,而socket程式設計是網路程式設計的基礎。利用socket可以實現客戶端和伺服器端的通訊。下面我先把客戶端和伺服器端的程式碼粘上去再進行詳細的分析。 package test1; import java.io.File; import java.io

JSON Web TokenJWT)使用步驟說明 JSON Web TokenJWT)原理用法介紹

在JSON Web Token(JWT)原理和用法介紹中,我們瞭解了JSON Web Token的原理和用法的基本介紹。本文我們著重講一下其使用的步驟: 一、JWT基本使用 Gradle下依賴 : compile 'com.auth0:java-jwt:3.4.0' 示例介紹: im

[Spring Boot實戰系列] - No.6 Springboot PageHelper實現後臺分頁

Springboot PageHelper實現後臺分頁 PageHelper是一個很強大的分頁外掛,在Springboot的專案中,如果後臺突然需要改為分頁返回,甚至無需更改過多程式碼即可獲得分頁的結果。 1. 前期程式碼準備 建立一個springboot專案,配置資料庫以及

Spring Boot 系列五:Spring Boot 通過devtools進行熱部署

前面已經分享過四篇學習文章: 1、Spring Boot 系統之一:Spring Boot 入門 2、Spring Boot 系統之二:Spring Boot 修改預設埠號和context path 3、Spring Boot 系統之三:Spring Boot 整合JdbcTemplat

Spring Boot Actuator 監控架構實戰使用

本 Chat 作為 Logging 的姊妹篇,來和大家一起整體認識一下 Spring Boot Actuator 及其在實際工作的使用。有整體到區域性,有原理到實戰,一起來學習一下 Actuator 的正確使用姿勢。通過此篇 Chat 我們可以瞭解到如下內容: Spri

Spring Boot 學習路——4 AOP註解方式實現列印日誌

前言:據XX統計,四分之一的程式碼都是日誌有關,日誌對於定位和解決問題尤為重要,以前公司的編碼規範中要求介面必須在日誌中記錄入參和返回值以及關鍵程式碼,引數部分完全可以用Spring的AOP——面向切面來實現。什麼叫AOP?百度:AOP(Aspect Oriented Pro

Spring Boot實戰系列《七》:實現登入國際化

Spring Boot實戰系列《七》:實現登入國際化 1.前言 上一篇文章說的是人事管理系統的登入設計,在設計好了登入頁面login.html的時候,不知道大家有沒有看到下方有一箇中文,英文按鈕。一般逼格高點的專案,都是需要國際化的。 那麼我們本篇文章就說一下關於spring b

Spring Boot 學習路——4.1 AOP註解方式實現列印日誌 詳解

以下內容轉自:https://www.cnblogs.com/lixiang1993/p/7447853.html1.宣告一個切面類,並把這個切面類加入到IOC容器中@Component@Aspectpublic class LogAspect{    @Pointcut(v

Spring Cloud實戰初級入門(四)— 利用Hystrix實現服務熔斷與服務監控

close 哪些 cati status netflix turn 遠程倉庫 monitor mri 目錄 1.環境介紹 2.服務監控 2.1 加入依賴 2.2 修改配置文件 2.3 修改啟動文件 2.4 監控服務 2.5 小結 3. 利用hystrix實現消費服務熔斷

Spring-boot】使用filter對request body引數進行校驗

@Slf4j public class ParameterCheckServletRequestWrapper extends HttpServletRequestWrapper { private byte[] requestBody; pr

spring進階 第一節 : spring boot 系列ssm專案實戰

spring進階 第一節 : spring boot 系列之ssm專案實戰 1.spring boot 介紹 特點 - 建立獨立的spring容器應用程式 - 內嵌容器(tomcat,jetty,undertow)無需w