jwt是爲了在網絡應用環境間傳遞聲明而執行的一種基於json的開放標準。該token被設計緊湊且安全的,特別適用於SSO場景。
jwt的聲明通常被用來在身份提供者和服務提供者之間傳遞被認證的用戶身份信息。git
eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MDAyIiwiZXhwIjoxNTEwOTcwMjU4fQ._FOqy5l44hODu3DjXh762LNUTLNQH15fdCUerdseDpmSKgkVSCjOyxQNTBKDSh3N-c83_pdEw5t6BdorgRU_kwgithub
JWT一般由三部分組成,頭信息(header)、消息體(body)、簽名(signature)
頭信息指定了JWT使用的簽名算法web
header={alg=HS512}算法
消息體包含了JWT的意圖,exp爲令牌過時時間spring
body={sub=testUsername, exp=1510886546}json
簽名經過私鑰生成安全
signature=kwq8a_B6WMqHOrEi-gFR5rRPmPL7qoShZJn0VFfXpXc1Yfw6BfVrliAP9C4UnXlqD3wRXO3mw_DDIdglN5lH9Qspringboot
jwt官網網絡
springboot官網app
<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>
@RestController @RequestMapping("/employee") public class EmployeeController { @GetMapping("/greeting") public String greeting() { return "Hello,World!"; } }
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)); }}
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; } }
@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())); } }
首先咱們先測試/employee/greeting 響應以下:
{
"timestamp": 1510887634904,
"status": 403,
"error": "Forbidden",
"message": "Access Denied",
"path": "/employee/greeting"
}
很明顯,狀態碼爲403,此刻咱們若是先登陸拿到token後再測試呢,測試以下
登陸成功後,咱們能夠看到headers中已經帶有jwt
authorization →Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0VXNlcm5hbWUiLCJleHAiOjE1MTA4ODkxMDd9.FtdEM0p84ff5CzDcoiQhtm1MF_NfDH2Ij1jspxlTQhuCISIzYdoU40OsFoxam9F1EXeVw2GZdQmArVwMk6HO1A
因爲postman在通常狀況下不支持自定義header 這個時候咱們須要下載一個插件開啓interceptor 開啓後將authorization 放入header繼續測試:
這時咱們發現已經成功返回hello,world!
最後附上代碼GitHub地址:源碼下載