21. JWT를 위한 security 설정
by 볼빵빵오춘기User.java - object 만들기
- model 패키지 생성 후 User.java 생성 및 코드 작성한다.
- String roles ⇒ getRoles 하면 결과 USER, ADMIN 로 나올것이고, getRoleList하면 USER, ADMIN 가 ‘,’를 기준으로 짤려서 List에 들어감으로써 0번째 인덱스에는 USER, 1번째 인덱스에는 ADMIN이 들어갈 것이다.
- roles이 하나만 있다면 getRoleList()를 만들 필요 없다.
- 애초에 model패키지에 Role 이라는 model(=class)를 만들어서 아래 코드처럼 처리해도 된다.(대신 아래 코드처럼 만든다면 getRoleList()는 필요x)
⇒ 하지만 Role 만듦으로써 테이블 하나 더 추가하는 것이 불편하므로 이 강의에서는 메소드를 이용한다.
private Role roles; // USER, ADMIN
@Entity // DB 만들라는 어노테이션
@Data // getter, setter를 만들어주는 어노테이션
@NoArgsConstructor // 아무것도 없는 생성자를 만들어주는 어노테이션
@Table(name = "JWT_USER")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String username;
private String password;
private String roles; // USER, ADMIN
public List<String> getRoleList(){
if(this.roles.length()>0){
return Arrays.asList(this.roles.split(","));
}
return new ArrayList<>();
}
}
SecurityConfig.java - configure(HttpSecurity http)오버라이드
- config 패키지 생성 후 SecurityConfig.java 생성 및 코드 추가한다.
- WebSecurityConfigurerAdapter extends 해준다.
- configure(HttpSecurity http) 오버라이드 한다.
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final CorsFilter corsFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // session 사용x 의미. STATELESS 서버로 만들겠다는 의미
.and()
.formLogin().disable() // formLogin을 안쓰겠단 의미 why? jwt서버이기 때문에 id,pw form로그인을 안하기 때문에
.httpBasic().disable() // 기존 방식과 조금 다름을 알 수 있다.
.authorizeRequests() // 인증이 필요한 주소요청이 왔을 때 아래와 같이 권한 설정을 하겠다.
.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(); // 다른 요청은 권한 없이 접근가능
}
}
CorsConfig.java - corsFilter()
- config 패키지 밑에 CorsConfig.java 생성 후 코드 작성한다.
- 스프링 관리할 수 있도록 @Configuration 붙여준다.
- corsFilter() 을 빈으로 등록한다. (@Bean 붙여줌)
- config.setAllowCredentials(false) 면 js로 요청했을 때 응답이 오지않는다. (이렇게 해주기만 하면 의미 없음. SecurityConfig.java 에 Filter로 등록을 해줘야 함.)
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true); // 내 서버가 응답할 때 json을 자바스크립트에서 처리할 수 있게 할지를 설정하는 것
config.addAllowedOrigin("*"); // 모든 ip에 응당을 허용
config.addAllowedHeader("*"); // 모든 header에 응답을 허용
config.addAllowedMethod("*"); // 모든 post, get, put, delete, patch 요청을 허용하겠다.
source.registerCorsConfiguration("/api/**", config); // source에 "/api/**" 에 들어온 주소는 config설정을 따라라 해준다.
return new CorsFilter(source); // source 담은 CorsFilter를 return
}
}
SecurityConfig.java - configure(HttpSecurity http) 코드 추가 및 어노테이션 붙여주기
- 내서버는 addFilter(corsFilter) 코드에 넣어줌으로써 모든요청은 addFilter(corsFilter) 코드를 타게됨으로써 cors정책에서 벗어날 수 있다. 따라서CrossOrigin 요청이 와도 다 허용이 된다.
- cf) RestApiController.java 에 @CrossOrigin을 붙일 수 도 있지만 아래 코드와 적을 경우 인증이 필요한 요청은 다 거부된다.
⇒ 인증이 필요하지않은 요청만 허용이되고 인증이 필요한 요청 로그인을 해야지만 할 수 있는 요청은 아래와 같이 코드를 적는다고 해서 해결이 안된다. - ⇒ @CrossOrigin vs .addFilter(corsFilter)
- 인증이 없을 때 @CrossOrigin 사용가능하지만 인증이 있을 때는 시큐리티 필터에 등록을 해야만 한다.
@CrossOrigin
@RestController
public class RestApiController {
@Configuration // IoC 할 수 있도록
@EnableWebSecurity // Security 활성화
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final CorsFilter corsFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilter(corsFilter) // @CrossOrigin(인증x), 시큐리티 필터에 등록(인증o)
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.formLogin().disable()
.httpBasic().disable()
.authorizeRequests()
.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();
}
}
결과확인
- http://localhost:8080/home 요청을 해보면 요청거부가 안되는 것을 확인됐다.
Security를 쓰고는 있는데 Session을 사용하지않으니 모든 페이지로 접근이 가능한 것이다. - http://localhost:8080/api/v1/user/** , http://localhost:8080/api/v1/manager/** , http://localhost:8080/api/v1/admin/** 을 요청해보면 권한이 없어 403이뜬다.
- 위의 권한 페이지 말고 다른 페이지를 들어가면 현재는 404 하지만 요청거부가 되지않는다.
Security 강의와 다른 점
- .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
⇒ STATELESS 를 사용한다는 점 ⇒ 내 서버는 STATELESS 서버야! - .addFilter(corsFilter)
⇒ 내서버는 corsOrigin 정책을 안 쓸꺼야! 모든 요청을 허용할꺼야! - .formLogin().disable()
⇒ 내 서버는 formLogin을 안 쓸꺼야!
⇒ JWT서버 세팅할 시에는 전 프로젝트의 Security와 다른부분을 세팅해줘야한다.
'강의 따라하기 > JWT' 카테고리의 다른 글
23. JWT Filter 등록 테스트 (0) | 2024.08.25 |
---|---|
22. JWT Bearer 인증 방식 (0) | 2024.08.25 |
20. JWT위한 yml파일 세팅 (0) | 2024.08.25 |
19. JWT 프로젝트 세팅 (0) | 2024.08.25 |
18. JWT 구조이해 (0) | 2024.08.24 |
블로그의 정보
Hello 춘기's world
볼빵빵오춘기