Authentication
使用者身份驗證
登入後的資訊配置
登入後會進行授權 Authorization
詳細資訊可以見下面文章
1. 表單登入
最常見的方式帳號
/ 密碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired private UserDetailsService userDetailsService;
@Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .permitAll(); }
@Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService); } }
|
2. base on memory
基於記憶體的身份驗證適合於簡單應用或開發階段,可以快速設定使用者名和密碼。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("user").password(passwordEncoder().encode("password")).roles("USER") .and() .withUser("admin").password(passwordEncoder().encode("admin")).roles("ADMIN"); }
@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
|
3. JWT 登入
pom 依賴
1 2 3 4 5 6 7 8 9
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency>
|
spring config
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeRequests() .antMatchers("/login").permitAll() .anyRequest().authenticated() .and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); }
@Autowired private JwtRequestFilter jwtRequestFilter; }
|
JWT util
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| @Component public class JwtUtil { private String secret = "yourSecretKey";
public String generateToken(UserDetails userDetails) { Map<String, Object> claims = new HashMap<>(); return Jwts.builder().setClaims(claims).setSubject(userDetails.getUsername()) .setIssuedAt(new Date(System.currentTimeMillis())) .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10)) .signWith(SignatureAlgorithm.HS256, secret).compact(); }
public Boolean validateToken(String token, UserDetails userDetails) { final String username = getUsernameFromToken(token); return (username.equals(userDetails.getUsername()) && !isTokenExpired(token)); }
private Boolean isTokenExpired(String token) { final Date expiration = getExpirationDateFromToken(token); return expiration.before(new Date()); }
private Date getExpirationDateFromToken(String token) { return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody().getExpiration(); }
private String getUsernameFromToken(String token) { return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody().getSubject(); } }
|
JWT filter
在每次request 時自動檢查token
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| @Component public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired private MyUserDetailsService userDetailsService;
@Autowired private JwtUtil jwtUtil;
@Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { final String authorizationHeader = request.getHeader("Authorization");
String username = null; String jwt = null;
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { jwt = authorizationHeader.substring(7); username = jwtUtil.getUsernameFromToken(jwt); }
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtUtil.validateToken(jwt, userDetails)) { UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken( userDetails, null, userDetails.getAuthorities()); usernamePasswordAuthenticationToken .setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken); } } chain.doFilter(request, response); } }
|
密碼加密
加密待補