使用JWT實現Spring Boot令牌認證
如何可靠實現Rest服務和客戶端之間的使用者身份驗證/授權的方式?
最原始的方式是為每個請求傳送基本的HTTP驗證頭部憑證資訊(使用者名稱/密碼),但這需要將這些憑證儲存在記憶體中,服務必須每次檢查這些憑證(口令雜湊操作是很費CPU的昂貴操作)。所以這不是最好的主意。
還有一種方式,REST服務使用令牌系統實現安全驗證。標準令牌系統在成功登入時返回“令牌”(只是一個長的唯一字串的隨機字元,例如GUID)。客戶端然後在每次請求的HTTP授權報頭中傳送此令牌。在處理請求的每個服務中,然後在後端伺服器中查詢上下文分解分析該令牌。上下文可以儲存在DB中,也可從Redis快取中檢索,或簡單地儲存在記憶體的雜湊表中。這種方法的缺點是,對於每個REST方法,您都將需要在資料庫或快取中執行查詢。
JSON Web Tokens(或簡稱JWT)也是一種令牌,它不僅是使用者唯一的令牌,而且還包含該使用者所需的任何資訊,即所謂的宣告。最基本的宣告是“Subject主題”(基本上是唯一的使用者ID),但是令牌可以擴充套件為包括任何你想要的資訊,可以是api訪問許可權或使用者角色; 您可以在使用者登入時簡單地向使用者新增“角色Role”陣列,其中包含“使用者”許可權和“管理”許可權。只要客戶端將JWT傳送到伺服器,就可以從JWT檢索這些宣告。
顯然,這個令牌是純文字,新增設定很方便;JWT使用安全金鑰加密(僅伺服器已知)或簽名。JWT使用的最常見的方法是透過簽名方式使用。這個JWT的“簽名”位稱為JWS,JSON Web Signature。當您希望客戶端能夠讀取的令牌中資訊時,可以使用此方法。base-64編碼用於簽名但不會加密。
另一種方法是使用JWE,JSON Web Encryption。使用JSON Web加密,您可以使用行業標準加密方法來加密令牌的內容。只有伺服器可以建立和解密令牌,因此這意味著客戶端無法讀取或更改內容,因為它不知道怎麼加密的。
讓我們來看一些實際的程式碼。開源小例子專案按這裡,使用spring boot實現JWT的案例。
首先,我們從登陸開始。它由/ user / login路由處理:
當使用者使用正確的密碼登入時,他會收到以下令牌:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJtQGFib3VsbGFpdGUubWUiLCJyb2xlcyI6InVzZXIiLCJpYXQiOjE0ODYyMDYwNjd9.nbppPf6DIl3f3d79EGouJ1cN599R0JELjAiGHXUqSD0
這個“令牌”之後會用於客戶端對伺服器的後續API呼叫系列請求。這裡的標準方法是傳送具有“Bearer”令牌的授權報頭。HTTP頭部將是:
authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJtQGFib3VsbGFpdGUubWUiLCJyb2xlcyI6InVzZXIiLCJpYXQiOjE0ODYyMDU3MTh9.N3quHsQvaqzpCLIPhm7-5_gvmK9TxVrKygCEiis27h
SpringBootJwtApplication會配置一個過濾器。Servlet過濾器可以使用HttpRequests做各種事情,我們將使用這個過濾器來保護我們的“安全”端點。你可以看到SpringBootJwtApplication類將我們的JwtFilter配置為只對“/ secure / *”端點執行操作:
2
這樣,當我們呼叫/user/login沒有授權頭時,它不會出錯。過濾器負責檢查正確的授權頭是否存在以及Http頭部中的令牌是否有效:
Jwt解析器使用與簽名相同的金鑰來檢查令牌簽名。如果金鑰有效,我們就在請求物件中儲存包含一些使用者資訊(電子郵件,角色)的“Claims”,以便API端點可以使用它。
最後但並非最不重要的是,我們呼叫chain.doFilter這樣,沒有它,請求不會傳遞到我們的控制器。
現在我們有了過濾器,我們可以定義一些漂亮的超級安全的API方法,比如:
您可以使用像Postman這樣的REST客戶端演示這個例子。
最原始的方式是為每個請求傳送基本的HTTP驗證頭部憑證資訊(使用者名稱/密碼),但這需要將這些憑證儲存在記憶體中,服務必須每次檢查這些憑證(口令雜湊操作是很費CPU的昂貴操作)。所以這不是最好的主意。
還有一種方式,REST服務使用令牌系統實現安全驗證。標準令牌系統在成功登入時返回“令牌”(只是一個長的唯一字串的隨機字元,例如GUID)。客戶端然後在每次請求的HTTP授權報頭中傳送此令牌。在處理請求的每個服務中,然後在後端伺服器中查詢上下文分解分析該令牌。上下文可以儲存在DB中,也可從Redis快取中檢索,或簡單地儲存在記憶體的雜湊表中。這種方法的缺點是,對於每個REST方法,您都將需要在資料庫或快取中執行查詢。
JSON Web Tokens(或簡稱JWT)也是一種令牌,它不僅是使用者唯一的令牌,而且還包含該使用者所需的任何資訊,即所謂的宣告。最基本的宣告是“Subject主題”(基本上是唯一的使用者ID),但是令牌可以擴充套件為包括任何你想要的資訊,可以是api訪問許可權或使用者角色; 您可以在使用者登入時簡單地向使用者新增“角色Role”陣列,其中包含“使用者”許可權和“管理”許可權。只要客戶端將JWT傳送到伺服器,就可以從JWT檢索這些宣告。
顯然,這個令牌是純文字,新增設定很方便;JWT使用安全金鑰加密(僅伺服器已知)或簽名。JWT使用的最常見的方法是透過簽名方式使用。這個JWT的“簽名”位稱為JWS,JSON Web Signature。當您希望客戶端能夠讀取的令牌中資訊時,可以使用此方法。base-64編碼用於簽名但不會加密。
另一種方法是使用JWE,JSON Web Encryption。使用JSON Web加密,您可以使用行業標準加密方法來加密令牌的內容。只有伺服器可以建立和解密令牌,因此這意味著客戶端無法讀取或更改內容,因為它不知道怎麼加密的。
讓我們來看一些實際的程式碼。開源小例子專案按這裡,使用spring boot實現JWT的案例。
首先,我們從登陸開始。它由/ user / login路由處理:
@RequestMapping(value = "/login", method = RequestMethod.POST) public String login(@RequestBody User login) throws ServletException { String jwtToken = ""; if (login.getEmail() == null || login.getPassword() == null) { throw new ServletException("Please fill in username and password"); } String email = login.getEmail(); String password = login.getPassword(); User user = userService.findByEmail(email); if (user == null) { throw new ServletException("User email not found."); } String pwd = user.getPassword(); if (!password.equals(pwd)) { throw new ServletException("Invalid login. Please check your name and password."); } jwtToken = Jwts.builder().setSubject(email).claim("roles", "user").setIssuedAt(new Date()) .signWith(SignatureAlgorithm.HS256, "secretkey").compact(); return jwtToken; } <p class="indent"> |
當使用者使用正確的密碼登入時,他會收到以下令牌:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJtQGFib3VsbGFpdGUubWUiLCJyb2xlcyI6InVzZXIiLCJpYXQiOjE0ODYyMDYwNjd9.nbppPf6DIl3f3d79EGouJ1cN599R0JELjAiGHXUqSD0
這個“令牌”之後會用於客戶端對伺服器的後續API呼叫系列請求。這裡的標準方法是傳送具有“Bearer”令牌的授權報頭。HTTP頭部將是:
authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJtQGFib3VsbGFpdGUubWUiLCJyb2xlcyI6InVzZXIiLCJpYXQiOjE0ODYyMDU3MTh9.N3quHsQvaqzpCLIPhm7-5_gvmK9TxVrKygCEiis27h
SpringBootJwtApplication會配置一個過濾器。Servlet過濾器可以使用HttpRequests做各種事情,我們將使用這個過濾器來保護我們的“安全”端點。你可以看到SpringBootJwtApplication類將我們的JwtFilter配置為只對“/ secure / *”端點執行操作:
final FilterRegistrationBean registrationBean = new FilterRegistrationBean(); registrationBean.setFilter(new JwtFilter()); registrationBean.addUrlPatterns("/secure/*"); return registrationBean; <p class="indent"> |
2
這樣,當我們呼叫/user/login沒有授權頭時,它不會出錯。過濾器負責檢查正確的授權頭是否存在以及Http頭部中的令牌是否有效:
public void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain chain) throws IOException, ServletException { final HttpServletRequest request = (HttpServletRequest) req; final HttpServletResponse response = (HttpServletResponse) res; final String authHeader = request.getHeader("authorization"); if ("OPTIONS".equals(request.getMethod())) { response.setStatus(HttpServletResponse.SC_OK); chain.doFilter(req, res); } else { if (authHeader == null || !authHeader.startsWith("Bearer ")) { throw new ServletException("Missing or invalid Authorization header"); } final String token = authHeader.substring(7); try { final Claims claims = Jwts.parser().setSigningKey("secretkey").parseClaimsJws(token).getBody(); request.setAttribute("claims", claims); } catch (final SignatureException e) { throw new ServletException("Invalid token"); } chain.doFilter(req, res); } } <p class="indent"> |
Jwt解析器使用與簽名相同的金鑰來檢查令牌簽名。如果金鑰有效,我們就在請求物件中儲存包含一些使用者資訊(電子郵件,角色)的“Claims”,以便API端點可以使用它。
最後但並非最不重要的是,我們呼叫chain.doFilter這樣,沒有它,請求不會傳遞到我們的控制器。
現在我們有了過濾器,我們可以定義一些漂亮的超級安全的API方法,比如:
@RequestMapping("/user/users") public String loginSuccess() { return "Login Successful!"; } <p class="indent"> |
您可以使用像Postman這樣的REST客戶端演示這個例子。
相關文章
- OAuth2.0實戰!使用JWT令牌認證!OAuthJWT
- Spring Security OAuth2.0認證授權三:使用JWT令牌SpringOAuthJWT
- koa 實現 jwt 認證JWT
- 使用 Jwt-Auth 實現 API 使用者認證以及無痛重新整理訪問令牌JWTAPI
- Spring Boot Security OAuth2 實現支援JWT令牌的授權伺服器Spring BootOAuthJWT伺服器
- 使用 Spring Security JWT 令牌簽名實現 REST API 安全性SpringJWTRESTAPI
- Spring Boot使用JWT進行token驗證Spring BootJWT
- Laravel 5.5 使用 Jwt-Auth 實現 API 使用者認證以及無痛重新整理訪問令牌LaravelJWTAPI
- express實現JWT使用者認證系統ExpressJWT
- 在Spring Boot中實現OAuth2.0認證Spring BootOAuth
- Laravel 5.7 和 JSON Web 令牌(tymon/jwt-auth) - 使用者認證LaravelJSONWebJWT
- [譯] Angular 安全 —— 使用 JSON 網路令牌(JWT)的身份認證:完全指南AngularJSONJWT
- 譯見|構建使用者管理微服務(五):使用 JWT 令牌和 Spring Security 來實現身份驗證微服務JWTSpring
- Spring Security 實戰乾貨:使用 JWT 認證訪問介面SpringJWT
- 瞭解如何使用JSON Web令牌(JWT)實現訪問授權驗證JSONWebJWT
- JWT實現登入認證例項JWT
- ASP.NET Core - JWT認證實現ASP.NETJWT
- Spring Boot 整合 Sa-Token 實現登入認證Spring Boot
- Node.js的Koa實現JWT使用者認證Node.jsJWT
- 實戰!Spring Boot Security+JWT前後端分離架構登入認證!Spring BootJWT後端架構
- 實戰!spring Boot security+JWT 前後端分離架構認證登入!Spring BootJWT後端架構
- Spring Boot中使用token:jwtSpring BootJWT
- SpringBoot整合Spring security JWT實現介面許可權認證Spring BootJWT
- 動態令牌認證
- Spring Boot 整合 Shiro實現認證及授權管理Spring Boot
- JWT 令牌JWT
- 基於JWT標準的使用者認證介面實現JWT
- Spring Boot + Security + JWT 實現Token驗證+多Provider——登入系統Spring BootJWTIDE
- 使用 JWT 認證使用者身份JWT
- 七、Spring Boot整合Spring Security之前後分離認證最佳實現Spring Boot
- Laravel6.0 使用 Jwt-auth 實現多使用者介面認證LaravelJWT
- 微服務架構 | 7.2 構建使用 JWT 令牌儲存的 OAuth2 安全認證微服務架構JWTOAuth
- 使用 JWT 身份驗證保護你的 Spring Boot 應用JWTSpring Boot
- Express + JWT使用者認證最輕實踐ExpressJWT
- JWT 多表認證JWT
- 安全令牌JWTJWT
- PHP 使用 jwt 使用者身份認證PHPJWT
- Spring Security認證器實現Spring