IT

스프링시큐리티 인액션 8장

프로개발러 2023. 8. 4. 11:22
반응형
http.authorizeRequests()
        .mvcMatchers("/hello").hasRole("ADMIN")
        .mvcMatchers("/ciao").hasRole("MANAGER")
        .anyRequest().permitAll();
.authorizeRequests()
.antMatchers("/css/**", "/assets/**", "/favicon/**", "/fonts/**", "/images/**", "/js/**", "/lib/**", "/favicon.ico").permitAll()

antMatchers vs mvcMatchers

mvcMatchers는 처음 봐서 찾아봄.

 

https://velog.io/@topy/antMatchers-vs-mvcMatchers

 

antMatchers vs mvcMatchers

antMatchers vs mvcMatchers

velog.io

 

  • antMatchers("/test")는 정확한 /test URL만 일치.
  • mvcMatchers("/test")는 /test, /test/, /test.html, /test.xyz 등 다양하게 일치

위의 결과가 바로 antMatchers의 단점이다.
antMatchers는 url 뒤에 /가 붙어있으면 이것을 인식하지 못한다.
그 이유는 REST 아키텍처 규칙상 URI 끝에는 슬래시(/)가 붙지 않아야 하므로, ‘/test/’ URI 요청을 ‘/test’로 인식해버려 접근을 허용하기 때문이다.

 

 

 

스프링시큐리티 3에서는 requestMatchers를 사용.

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {

   private final ProgramMngDao programDao;

   @Bean
   public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
.requestMatchers("js/**", "css/**", "lib/**").permitAll()

 

 

 

@Override
@Bean
public UserDetailsService userDetailsService() {
    var manager = new InMemoryUserDetailsManager();

    var user1 = User.withUsername("john")
            .password("12345")
            .roles("ADMIN")
            .build();

    var user2 = User.withUsername("jane")
            .password("12345")
            .roles("MANAGER")
            .build();

    manager.createUser(user1);
    manager.createUser(user2);

    return manager;
}

@Bean
public PasswordEncoder passwordEncoder() {
    return NoOpPasswordEncoder.getInstance();
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.httpBasic();

    http.authorizeRequests()
            .mvcMatchers("/hello").hasRole("ADMIN")
            .mvcMatchers("/ciao").hasRole("MANAGER")
            .anyRequest().permitAll();
            //.anyRequest().denyAll();
            //.anyRequest().authenticated();
}

C:\Users\user>curl http://localhost:8080/hola --user "john:12345"
Hola!

 

 

C:\Users\user>curl http://localhost:8080/hello --user "john:12345"
Hello!

 

 

C:\Users\user>curl http://localhost:8080/ciao --user "john:12345"
{"timestamp":"2023-08-04T02:03:25.971+00:00","status":403,"error":"Forbidden","message":"","path":"/ciao"}

 

 

 

그 이외의 모든 리퀘스트는 허용할 경우라도

.anyRequest().permitAll();

잘못된 사용자로 접근하면 에러남

C:\Users\user>curl http://localhost:8080/hola --user "john:12345xxx"
{"timestamp":"2023-08-04T02:04:32.732+00:00","status":401,"error":"Unauthorized","message":"","path":"/hola"}

 

 

C:\Users\user>curl http://localhost:8080/hola
Hola!

 

 

 

.anyRequest().authenticated();

인증된 사용자만 접근가능.

 

 

 

HttpMethod.GET는 처음 알음...

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.httpBasic();

    http.authorizeRequests()
            .mvcMatchers(HttpMethod.GET, "/a").authenticated()
            .mvcMatchers(HttpMethod.POST, "/a").permitAll()
            .anyRequest().denyAll();

    http.csrf().disable();
}

컨트롤러 소스

@RestController
public class TestController {

    @PostMapping("/a")
    public String postEndpointA() {
        return "Works!";
    }

    @GetMapping("/a")
    public String getEndpointA() {
        return "Works!";
    }

    @GetMapping("/a/b")
    public String getEnpointB() {
        return "Works!";
    }

    @GetMapping("/a/b/c")
    public String getEnpointC() {
        return "Works!";
    }
}

 

/a uri의 GET은 무조건 인증되어야 허용 가능.

.mvcMatchers(HttpMethod.GET, "/a").authenticated()

 

C:\Users\user>curl -X GET http://localhost:8080/a
{"timestamp":"2023-08-04T02:12:23.459+00:00","status":401,"error":"Unauthorized","message":"","path":"/a"}

 

 

그다음 내가 헷갈려 하던 부분

MVC선택기로 경로 일치에 이용되는 일반적인 식
/a           /a경로만
/a/*         *연산자는 한 경로 이름만 대체.  /a/b 또는 /a/c와는 일치, /a/b/c는 안됨
/a/**        **연산자는 여러 경로 이름을 대체. 이 경우 /a /a/b  a/b/c가 모두 일치
/a/{param}  /a/경로에 매개변수 포함
/a/{param:regex}   매개변수값과 주어진 정규식이 일치할 경우 + /a경로

 

 

정규식 활용해서 이메일 형태일 경우만 인증 허용하려면

@Configuration
public class ProjectConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.httpBasic();

        http.authorizeRequests()
            .mvcMatchers("/email/{email:.*(.+@.+\\.com)}")
                .permitAll()
            .anyRequest()
                .denyAll();
    }
}

 

 

@RestController
public class TestController {

    @GetMapping("/email/{email}")
    public String video(@PathVariable String email) {
        return "Allowed for email " + email;
    }

}

C:\Users\user>curl -X GET http://localhost:8080/email/test@naver.com
Allowed for email test@naver.com


C:\Users\user>curl -X GET http://localhost:8080/email/test@naver.c
{"timestamp":"2023-08-04T02:20:59.249+00:00","status":401,"error":"Unauthorized","message":"","path":"/email/test@naver.c"}


C:\Users\user>curl -X GET http://localhost:8080/email/test@naver.net
{"timestamp":"2023-08-04T02:21:04.696+00:00","status":401,"error":"Unauthorized","message":"","path":"/email/test@naver.net"}

반응형