특정 URL에 대해 스프링 보안을 비활성화하는 방법


85

상태 비 저장 스프링 보안을 사용하고 있지만 가입시 스프링 보안을 비활성화하고 싶습니다.

antMatchers("/api/v1/signup").permitAll().

하지만 작동하지 않습니다. 아래 오류가 발생합니다.

 message=An Authentication object was not found in the SecurityContext, type=org.springframework.security.authentication.AuthenticationCredentialsNotFoundException

이것은 스프링 보안 필터가 작동하고 있음을 의미한다고 생각합니다.

내 URL의 순서는 항상 "/ api / v1"입니다.

내 봄 구성은

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

         http.
         csrf().disable().
         sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).
         and().
         authorizeRequests().
         antMatchers("/api/v1/signup").permitAll().
         anyRequest().authenticated().
         and().
         anonymous().disable();
        http.addFilterBefore(new AuthenticationFilter(authenticationManager()), BasicAuthenticationFilter.class);
    }

내 인증 필터는

@Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = asHttp(request);
        HttpServletResponse httpResponse = asHttp(response);

        String username = httpRequest.getHeader("X-Auth-Username");
        String password = httpRequest.getHeader("X-Auth-Password");
        String token = httpRequest.getHeader("X-Auth-Token");

        String resourcePath = new UrlPathHelper().getPathWithinApplication(httpRequest);

        try {

            if (postToAuthenticate(httpRequest, resourcePath)) {            
                processUsernamePasswordAuthentication(httpResponse, username, password);
                return;
            }

            if(token != null){
                processTokenAuthentication(token);
            }
            chain.doFilter(request, response);
        } catch (InternalAuthenticationServiceException internalAuthenticationServiceException) {
            SecurityContextHolder.clearContext();
            logger.error("Internal authentication service exception", internalAuthenticationServiceException);
            httpResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        } catch (AuthenticationException authenticationException) {
            SecurityContextHolder.clearContext();
            httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, authenticationException.getMessage());
        } finally {
        }
    }

     private HttpServletRequest asHttp(ServletRequest request) {
            return (HttpServletRequest) request;
        }

        private HttpServletResponse asHttp(ServletResponse response) {
            return (HttpServletResponse) response;
        }

        private boolean postToAuthenticate(HttpServletRequest httpRequest, String resourcePath) {
            return Constant.AUTHENTICATE_URL.equalsIgnoreCase(resourcePath) && httpRequest.getMethod().equals("POST");
        }

        private void processUsernamePasswordAuthentication(HttpServletResponse httpResponse,String username, String password) throws IOException {
            Authentication resultOfAuthentication = tryToAuthenticateWithUsernameAndPassword(username, password);
            SecurityContextHolder.getContext().setAuthentication(resultOfAuthentication);
            httpResponse.setStatus(HttpServletResponse.SC_OK);
            httpResponse.addHeader("Content-Type", "application/json");
            httpResponse.addHeader("X-Auth-Token", resultOfAuthentication.getDetails().toString());
        }

        private Authentication tryToAuthenticateWithUsernameAndPassword(String username,String password) {
            UsernamePasswordAuthenticationToken requestAuthentication = new UsernamePasswordAuthenticationToken(username, password);
            return tryToAuthenticate(requestAuthentication);
        }

        private void processTokenAuthentication(String token) {
            Authentication resultOfAuthentication = tryToAuthenticateWithToken(token);
            SecurityContextHolder.getContext().setAuthentication(resultOfAuthentication);
        }

        private Authentication tryToAuthenticateWithToken(String token) {
            PreAuthenticatedAuthenticationToken requestAuthentication = new PreAuthenticatedAuthenticationToken(token, null);
            return tryToAuthenticate(requestAuthentication);
        }

        private Authentication tryToAuthenticate(Authentication requestAuthentication) {
            Authentication responseAuthentication = authenticationManager.authenticate(requestAuthentication);
            if (responseAuthentication == null || !responseAuthentication.isAuthenticated()) {
                throw new InternalAuthenticationServiceException("Unable to authenticate Domain User for provided credentials");
            }
            logger.debug("User successfully authenticated");
            return responseAuthentication;
        }

내 컨트롤러는

@RestController
public class UserController {

    @Autowired
    UserService userService;

    /**
     * to pass user info to service
     */
    @RequestMapping(value = "api/v1/signup",method = RequestMethod.POST)
    public String saveUser(@RequestBody User user) {
        userService.saveUser(user);
        return "User registerted successfully";
    }
}

나는 봄에 완전히 새롭습니다, 그것을하는 방법을 도와주세요?


답변:


156

사용할 때 permitAll 모든 인증 된 사용자를 의미하지만 익명 액세스를 비활성화하여 작동하지 않습니다.

당신이 원하는 것은 객체와 패턴 configure을 취하는 메소드를 재정의하기 위해 특정 URL을 무시 하는 것입니다.WebSecurityignore

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/api/v1/signup");
}

그리고 HttpSecurity부품 에서 그 선을 제거하십시오 . 이것은 Spring Security에이 URL을 무시하고 어떤 필터도 적용하지 않도록 지시합니다.


4
이것은 어떤 파일에 기록됩니까?
Jacob Zimmerman

3
@JacobZimmerman spring.io/blog/2013/07/03/... 웹 보안 클래스의 설정자
Askar IBRAGIMOV

1
그냥 당신이 확장해야 추가하고 싶은 WebSecurityConfigurerAdapter하고 overridemethod안에.
muasif80

19

더 나은 방법이 있습니다.

http
    .authorizeRequests()
    .antMatchers("/api/v1/signup/**").permitAll()
    .anyRequest().authenticated()

3
이 스 니펫은 어디에서 호출해야합니까?
Viacheslav Shalamov

@ViacheslavShalamov 귀하 WebSecurityConfig extends WebSecurityConfigurerAdapterconfigure(HttpSecurity http)방법에서. 참조 baeldung.com/java-config-spring-security
JAC

1
이것은 인터넷에서 가장 일반적이며 실제로 잘못된 관행입니다. 모든 것을 허용하면 여전히 인증이 필요하지만 마침내 허용한다는 의미입니다. 그렇다면 가입 액세스를 위해 인증을 수행해야하는 이유는 무엇입니까 (인증 필터가 계속 트리거된다는 의미)?
Chao

13
<http pattern="/resources/**" security="none"/>

또는 Java 구성 :

web.ignoring().antMatchers("/resources/**");

이전 대신 :

 <intercept-url pattern="/resources/**" filters="none"/>

특급. 로그인 페이지에 대한 보안 비활성화 :

  <intercept-url pattern="/login*" filters="none" />

9

이것은 귀하의 질문에 대한 완전한 대답이 아닐 수 있지만 csrf 보호를 비활성화하는 방법을 찾고 있다면 다음을 수행 할 수 있습니다.

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/web/admin/**").hasAnyRole(ADMIN.toString(), GUEST.toString())
                .anyRequest().permitAll()
                .and()
                .formLogin().loginPage("/web/login").permitAll()
                .and()
                .csrf().ignoringAntMatchers("/contact-email")
                .and()
                .logout().logoutUrl("/web/logout").logoutSuccessUrl("/web/").permitAll();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("admin").password("admin").roles(ADMIN.toString())
                .and()
                .withUser("guest").password("guest").roles(GUEST.toString());
    }

}

전체 구성을 포함했지만 핵심은 다음과 같습니다.

.csrf().ignoringAntMatchers("/contact-email")

2

@M. Deinum이 이미 답변을 썼습니다.

나는 api로 시도했다 /api/v1/signup. 필터 / 사용자 정의 필터를 우회하지만 브라우저에서에 대한 추가 요청을 호출 /favicon.ico하므로 web.ignoring ()에도 추가하면 저에게 효과적입니다.

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/api/v1/signup", "/favicon.ico");
}

위의 질문에는 이것이 필요하지 않을 수도 있습니다.


2

여러 API 엔드 포인트를 무시하려면 다음과 같이 사용할 수 있습니다.

 @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.csrf().disable().authorizeRequests() 
            .antMatchers("/api/v1/**").authenticated()
            .antMatchers("api/v1/authenticate**").permitAll()
            .antMatchers("**").permitAll()
            .and().exceptionHandling().and().sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

0

나는 여기에 해결책이 같은 문제에 직면했다. ( 설명 )

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
            .antMatchers(HttpMethod.POST,"/form").hasRole("ADMIN")  // Specific api method request based on role.
            .antMatchers("/home","/basic").permitAll()  // permited urls to guest users(without login).
            .anyRequest().authenticated()
            .and()
        .formLogin()       // not specified form page to use default login page of spring security.
            .permitAll()
             .and()
        .logout().deleteCookies("JSESSIONID")  // delete memory of browser after logout.

        .and()
        .rememberMe().key("uniqueAndSecret"); // remember me check box enabled.

    http.csrf().disable();  **// ADD THIS CODE TO DISABLE CSRF IN PROJECT.**
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.