什麼是JWT(Json Web Token)
jwt是為了在網絡應用環境間傳遞聲明而執行的一種基于json的開放标準。該token被設計緊湊且安全的,特别适用于SSO場景。
jwt的聲明一般被用來在身份提供者和服務提供者之間傳遞被認證的使用者身份資訊。
JWT長什麼樣
eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MDAyIiwiZXhwIjoxNTEwOTcwMjU4fQ._FOqy5l44hODu3DjXh762LNUTLNQH15fdCUerdseDpmSKgkVSCjOyxQNTBKDSh3N-c83_pdEw5t6BdorgRU_kw
JWT的構成
JWT通常由三部分組成,頭資訊(header)、消息體(body)、簽名(signature)
頭資訊指定了JWT使用的簽名算法
header={alg=HS512}
消息體包含了JWT的意圖,exp為令牌過期時間
body={sub=testUsername, exp=1510886546}
簽名通過私鑰生成
signature=kwq8a_B6WMqHOrEi-gFR5rRPmPL7qoShZJn0VFfXpXc1Yfw6BfVrliAP9C4UnXlqD3wRXO3mw_DDIdglN5lH9Q
使用springboot內建jwt
jwt官網
springboot官網
引用依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.7.0</version> </dependency>
建構普通rest接口
@RestController @RequestMapping("/employee") public class EmployeeController { @GetMapping("/greeting") public String greeting() { return "Hello,World!"; } }
JwtLoginFilter
}public class JwtLoginFilter extends UsernamePasswordAuthenticationFilter { private AuthenticationManager authenticationManager; public JwtLoginFilter(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { Employee employee = new Employee(); return authenticationManager.authenticate( new UsernamePasswordAuthenticationToken( employee.getUsername(), employee.getPassword(), new ArrayList<>() ) ); } @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { String token = Jwts.builder() .setSubject(((User) authResult.getPrincipal()).getUsername()) .setExpiration(new Date(System.currentTimeMillis() + 30 * 60 * 1000)) .signWith(SignatureAlgorithm.HS512, "JWTSecret") .compact(); response.addHeader("Authorization", JwtUtils.getTokenHeader(token)); }
JwtAuthenticationFilter
public class JwtAuthenticationFilter extends BasicAuthenticationFilter { public JwtAuthenticationFilter(AuthenticationManager authenticationManager) { super(authenticationManager); } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { String header = request.getHeader("Authorization"); if (header == null || !header.startsWith(JwtUtils.getAuthorizationHeaderPrefix())) { chain.doFilter(request, response); return; } UsernamePasswordAuthenticationToken authenticationToken = getUsernamePasswordAuthenticationToken(header); SecurityContextHolder.getContext().setAuthentication(authenticationToken); chain.doFilter(request, response); } private UsernamePasswordAuthenticationToken getUsernamePasswordAuthenticationToken(String token) { String user = Jwts.parser() .setSigningKey("PrivateSecret") .parseClaimsJws(token.replace(JwtUtils.getAuthorizationHeaderPrefix(), "")) .getBody() .getSubject(); if (null != user) { return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>()); } return null; } }
SecurityConfiguration
@Configuration @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Override public void configure(WebSecurity web) throws Exception { super.configure(web); } @Override protected void configure(HttpSecurity http) throws Exception { http.cors().and().csrf().disable().authorizeRequests() .anyRequest().authenticated() .and() .addFilter(new JwtLoginFilter(authenticationManager())) .addFilter(new JwtAuthenticationFilter(authenticationManager())); } }
使用postman測試
首先我們先測試/employee/greeting 響應如下:
{
"timestamp": 1510887634904,
"status": 403,
"error": "Forbidden",
"message": "Access Denied",
"path": "/employee/greeting"
很明顯,狀态碼為403,此刻我們如果先登入拿到token後再測試呢,測試如下
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiIDMmVWNhZTN4cTMxcTZiN2NiJDMhFWY5kzN5AzYiNmY9kXZLVmchh2cmQWYvxmb39GZ9Q2boRXZt9zNzgDMDRDOEVUOCZkM0MTOzIEN0kTOyEjMFBDR0YzN38CXlxWam9CXsFmbvNnclB3LclGch9CXzdXevwVbvNmLvFGZ19WeuUGdv52Lc9CX6MHc0RHaiojIsJye.jpg)
登入成功後,我們可以看到headers中已經帶有jwt
authorization →Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0VXNlcm5hbWUiLCJleHAiOjE1MTA4ODkxMDd9.FtdEM0p84ff5CzDcoiQhtm1MF_NfDH2Ij1jspxlTQhuCISIzYdoU40OsFoxam9F1EXeVw2GZdQmArVwMk6HO1A
由于postman在一般情況下不支援自定義header 這個時候我們需要下載下傳一個插件開啟interceptor 開啟後将authorization 放入header繼續測試:
這時我們發現已經成功傳回hello,world!
最後附上代碼GitHub位址:源碼下載下傳
本文轉載自
原文作者:胡運凡
原文連結:https://www.cnblogs.com/huyunfan/p/7850680.html