JWT
JWT ํ ํฐ์ผ๋ก ๋ก๊ทธ์ธ
๋ก๊ทธ์ธ์ ์๋๋ localhost:8080/login ์ ํธ์ถํ๋ฉด ์คํ๋ง ์ํ๋ฆฌํฐ๊ฐ ์์์ UserDetailsService ๋น์ ์ฐพ์ loadUserByUsername์ ํธ์ถํ๋๋ฐ filterChain ์์ formLogin์ disableํ๊ณ ์ปค์คํ ํํฐ๋ฅผ ๋ฑ๋กํด์ ๋ก๊ทธ์ธ์ ํ ๊ฒ์ด๋ค.
SecurityConfig.java
security ๊ธฐ๋ณธ์ ์ ์ด๋์ config์ ๊ฐ๋ค
@Configuration
@EnableWebSecurity // ์ํ๋ฆฌํฐ ํ์ฑํ -> ๊ธฐ๋ณธ ์คํ๋ง ํํฐ์ฒด์ธ์ ๋ฑ๋ก
public class SecurityConfig {
@Autowired
private UserRepository userRepository;
@Autowired
private CorsConfig corsConfig;
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.formLogin().disable()
.httpBasic().disable()
.apply(new MyCustomDsl()) // ์ปค์คํ
ํํฐ ๋ฑ๋ก
.and()
.authorizeRequests(authroize -> authroize.antMatchers("/api/v1/user/**")
.access("hasRole('ROLE_USER') or hasRole('ROLE_MANAGER') or hasRole('ROLE_ADMIN')")
.antMatchers("/api/v1/manager/**")
.access("hasRole('ROLE_MANAGER') or hasRole('ROLE_ADMIN')")
.antMatchers("/api/v1/admin/**")
.access("hasRole('ROLE_ADMIN')")
.anyRequest().permitAll())
.build();
}
public class MyCustomDsl extends AbstractHttpConfigurer<MyCustomDsl, HttpSecurity> {
@Override
public void configure(HttpSecurity http) throws Exception {
AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class);
http
.addFilter(corsConfig.corsFilter())
.addFilter(new JwtAuthenticationFilter(authenticationManager))
.addFilter(new JwtAuthorizationFilter(authenticationManager, userRepository));
}
}
}
JwtAutenticationFilter.java
๋ก๊ทธ์ธ์ ์คํ๋๋ ํํฐ๋ฅผ ์์๋ฐ์ ํํฐ๋ฅผ ๋ง๋ค์ด์ค์ SecurityConfig ์ ๋ฑ๋กํด์ค์ผํจ
UsernamePasswordAuthenticationFilter๋ AuthenticationManager๊ฐ ๋งค๊ฐ๋ณ์๋ก ํ์ํจ. ์์ SecurityConfig.java์ ํํฐ๋ฅผ ๋ฑ๋กํ๋ ๋ถ๋ถ์ ๋ณด๋ฉด AuthenticationManager ๊ฐ์ฒด๋ฅผ ์์ฑํด์ ๋๊ฒจ์ฃผ๋๊ฑธ ๋ณผ ์ ์์
PrincipalDetailsService ์ PrincipalDetails๋ security ๊ธฐ๋ณธ์ ์์ฑ๋์ด ์์, ์์ฑํด์ค์ผํจ
//์คํ๋ง ์ํ๋ฆฌํฐ์์ UsernamePasswordAuthenticationFilter ๊ฐ ์์
// /login ์์ฒญํด์ username,password ์ ์กํ๋ฉด ์ด ํํฐ๊ฐ ๋์์ ํจ, ๊ทผ๋ฐ formlogin์ disableํด๋์ ์ง๊ธ ์๋์ผ๋ก ์๋์ํจ
//๊ทธ๋์ ํํฐ๋ฅผ ์์๋ฐ์ ๋ง๋ค์ด์ฃผ๊ณ securityconfig์ ๋ฑ๋ก์์ผ ์ฃผ๋๊ฒ์
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter{
private final AuthenticationManager authenticationManager;
// Authentication ๊ฐ์ฒด ๋ง๋ค์ด์ ๋ฆฌํด => ์์กด : AuthenticationManager
// ์ธ์ฆ ์์ฒญ์์ ์คํ๋๋ ํจ์ => /login (๋ก๊ทธ์ธ์๋์ ์คํ๋จ)
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
System.out.println("JwtAuthenticationFilter : ์ง์
");
/*
* 1. username,password ๋ฐ์์
* 2. ์ ์์ธ์ง ๋ก๊ทธ์ธ ์๋๋ฅผ ํจ. authenticationManager๋ก ๋ก๊ทธ์ธ ์๋๋ฅผ ํ๋ฉด PrincipalDetailsService๊ฐ ํธ์ถ๋จ
* 3. loadUserByUsername ํจ์ ์คํ๋จ
* 4. PrincipalDetail๋ฅผ ์ธ์
์ ๋ด๊ณ -> ์ธ์
์ ์๋ด์์ฃผ๋ฉด ๊ถํ ๊ด๋ฆฌ๊ฐ ์๋จ
* 5. JWTํ ํฐ์ ๋ง๋ค์ด์ ์๋ต
*/
// request์ ์๋ username๊ณผ password๋ฅผ ํ์ฑํด์ ์๋ฐ Object๋ก ๋ฐ๊ธฐ
ObjectMapper om = new ObjectMapper();
LoginRequestDto loginRequestDto = null;
try {
loginRequestDto = om.readValue(request.getInputStream(), LoginRequestDto.class);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("JwtAuthenticationFilter : "+loginRequestDto);
// ์ ์ ๋ค์ํจ์ค์๋ ํ ํฐ ์์ฑ
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(
loginRequestDto.getUsername(),
loginRequestDto.getPassword());
System.out.println("JwtAuthenticationFilter : ํ ํฐ์์ฑ์๋ฃ");
// authenticate() ํจ์๊ฐ ํธ์ถ ๋๋ฉด ์ธ์ฆ ํ๋ก๋ฐ์ด๋๊ฐ ์ ์ ๋ํ
์ผ ์๋น์ค์
// loadUserByUsername(ํ ํฐ์ ์ฒซ๋ฒ์งธ ํ๋ผ๋ฉํฐ) ๋ฅผ ํธ์ถํ๊ณ
// UserDetails๋ฅผ ๋ฆฌํด๋ฐ์์ ํ ํฐ์ ๋๋ฒ์งธ ํ๋ผ๋ฉํฐ(credential)๊ณผ
// UserDetails(DB๊ฐ)์ getPassword()ํจ์๋ก ๋น๊ตํด์ ๋์ผํ๋ฉด
// Authentication ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด์ ํํฐ์ฒด์ธ์ผ๋ก ๋ฆฌํดํด์ค๋ค.
// Tip: ์ธ์ฆ ํ๋ก๋ฐ์ด๋์ ๋ํดํธ ์๋น์ค๋ UserDetailsService ํ์
// Tip: ์ธ์ฆ ํ๋ก๋ฐ์ด๋์ ๋ํดํธ ์ํธํ ๋ฐฉ์์ BCryptPasswordEncoder
// ๊ฒฐ๋ก ์ ์ธ์ฆ ํ๋ก๋ฐ์ด๋์๊ฒ ์๋ ค์ค ํ์๊ฐ ์์.
Authentication authentication =
authenticationManager.authenticate(authenticationToken);
PrincipalDetails principalDetailis = (PrincipalDetails) authentication.getPrincipal();
System.out.println("Authentication : "+principalDetailis.getUser().getUsername());
//authentication๊ฐ์ฒด๊ฐ session์์ญ์ ์ ์ฅ์ ํด์ผํ๊ณ ๊ทธ ๋ฐฉ๋ฒ์ด return ํด์ฃผ๋ฉด๋จ
//๊ทธ ์ด์ ๋ ๊ถํ ๊ด๋ฆฌ๋ฅผ ์ํ๋ฆฌํฐ๊ฐ ๋์ ํด์ฃผ๊ธฐ ๋๋ฌธ์ ํธํ๋ ค๊ณ ํ๋๊ฑฐ์
//๊ตณ์ด JWT ํ ํฐ์ ์ฌ์ฉํ๋ฉด์ ์ธ์
์ ๋ง๋ค ์ด์ ๊ฐ ์์ง๋ง ๋จ์ง ๊ถํ์ฒ๋ฆฌ ๋๋ฌธ์ ์ธ์
์ ๋ฃ์ด์ฃผ๋๊ฒ
return authentication;
}
//์์ ํจ์๊ฐ ์คํ์ด ์ข
๋ฃ๋๋ฉด(์ธ์ฆ์ด ์ ์์ผ๋ก ๋๋ฉด) ์ด์ด์ successfulAuthentication๊ฐ ์คํ๋จ
//JWTํ ํฐ์ ๋ง๋ค์ด์ requset์์ฒญํ ์ฌ์ฉ์์๊ฒ JWTํ ํฐ์ reponseํด์ค
// JWT Token ์์ฑํด์ response์ ๋ด์์ฃผ๊ธฐ
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication authResult) throws IOException, ServletException {
PrincipalDetails principalDetailis = (PrincipalDetails) authResult.getPrincipal();
//RSA๋ฐฉ์์ ์๋๊ณ Hash์ํธ ๋ฐฉ์
String jwtToken = JWT.create()
.withSubject(principalDetailis.getUsername()) //ํฌ๊ฒ ์ค์ํ์ง ์์
.withExpiresAt(new Date(System.currentTimeMillis()+JwtProperties.EXPIRATION_TIME)) //์ธ์ ๊น์ง ์ ํจํ ์ง ๋ง๋ฃ์๊ฐ
.withClaim("id", principalDetailis.getUser().getId())
.withClaim("username", principalDetailis.getUser().getUsername())
.sign(Algorithm.HMAC512(JwtProperties.SECRET));
response.addHeader(JwtProperties.HEADER_STRING, JwtProperties.TOKEN_PREFIX+jwtToken);
}
}
JwtProperties.java
public interface JwtProperties {
String SECRET = "cos"; // ์ฐ๋ฆฌ ์๋ฒ๋ง ์๊ณ ์๋ ๋น๋ฐ๊ฐ
int EXPIRATION_TIME = 864000000; // 10์ผ (1/1000์ด)
String TOKEN_PREFIX = "Bearer ";
String HEADER_STRING = "Authorization";
}
Last updated