JWT
JWT를 구현할 때 권한관리를 하기 위해 Authentication을 return 해야하는 이유
JANNNNNN
2024. 7. 8. 14:37
JWT를 공부하던 도중 Authentication 객체를 반환하는 이유가 권한 관리를 위해서라는 말이 이해가 가지 않아 정리해보기로 결심!
일단 저의 코드 구조를 대략적으로 적어보겠습니다.
User
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String username;
private String password;
private String roles; //USER, ADMIN
//하나의 유저당 role이 2개 이상일 경우를 대비해서!
public List<String> getRoleList(){
if(this.roles.length() > 0){
return Arrays.asList(this.roles.split(","));
}
return new ArrayList<>();
}
➡️roles가 있으므로, 권한이 필요함!
Security Config
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
}
- configure(HttpSecurity http): HTTP 요청에 대한 인가 설정을 구성합니다. 예를 들어, "/admin/**" 경로는 ADMIN 역할을 가진 사용자만 접근할 수 있도록 설정합니다.
- configure(AuthenticationManagerBuilder auth): 사용자 인증을 설정합니다. userDetailsService를 통해 사용자 정보를 조회하고, passwordEncoder()를 통해 비밀번호를 암호화하여 인증을 수행합니다.
Controller
@RestController
@RequestMapping("/api")
public class ApiController {
@GetMapping("/public")
public String publicEndpoint() {
return "Public endpoint accessed";
}
@GetMapping("/admin")
public String adminEndpoint() {
return "Admin endpoint accessed";
}
@GetMapping("/user")
public String userEndpoint() {
return "User endpoint accessed";
}
}
➡️/public은 모든 사용자에게 허용되고, /admin은 ADMIN 권한을 가진 사용자에게만 허용됩니다. /user는 인증된 모든 사용자에게 허용됩니다.
동작 방식 요약
- 사용자가 로그인을 하면 PrincipalDetailsService에서 사용자 정보와 권한을 조회해 UserDetails 객체를 생성합니다
- Spring Security는 UserDetails 객체를 Authentication 객체에 저장해 Security Context에 저장합니다.
- HTTP 요청이 들어올 때마다, Authentication 객체를 통해 사용자 권한을 확인하고 접근 제어를 수행합니다 !
Authentication 객체를 통해 사용자 권한을 확인하는 과정
1. 사용자 로그인
- 사용자가 아이디와 비밀번호로 로그인을 수행합니다.
- Spring Security는 UsernamePasswordAuthenticationToken을 생성해 사용자의 아이디와 비밀번호를 포함시킨 후 AuthenticationManager를 통해 인증을 시도합니다.
- AuthenticationManager는 AuthenticationProvider를 사용해 실제 인증을 수행하고, 성공하면 Authentication 객체를 반환합니다.
2. HTTP 요청 처리
- 사용자가 로그인 후, 다시 HTTP 요청을 보냅니다.
- 예를 들어 'api/admin' 엔드 포인트에 접근하는 것처럼!
- Spring Security는 SecurityContext에서 현재 사용자의 Authentication 객체를 가져옵니다.
- 해당 Authentication 객체를 통해 사용자의 권한을 확인합니다
- 예를 들어 hasRole("Admin")을 통해!
- 사용자가 권한을 가지고 있으면 요청을 허용하고 그렇지 않으면 접근을 거부합니다.