Cách tắt bảo mật mùa xuân cho url cụ thể


85

Tôi đang sử dụng bảo mật mùa xuân không trạng thái, nhưng trong trường hợp đăng ký, tôi muốn tắt bảo mật mùa xuân.

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

nhưng nó không hoạt động, tôi gặp lỗi bên dưới:

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

Tôi nghĩ điều này có nghĩa là bộ lọc bảo mật mùa xuân đang hoạt động

Thứ tự url của tôi luôn luôn sẽ là "/ api / v1"

Cấu hình mùa xuân của tôi là

@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);
    }

Bộ lọc xác thực của tôi là

@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;
        }

Bộ điều khiển của tôi là

@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";
    }
}

Tôi hoàn toàn mới vào mùa xuân, xin vui lòng giúp tôi làm thế nào để làm điều đó?


Câu trả lời:


156

Khi sử dụng permitAllnó có nghĩa là mọi người dùng được xác thực, tuy nhiên bạn đã vô hiệu hóa quyền truy cập ẩn danh để điều đó không hoạt động.

Những gì bạn muốn là bỏ qua các URL nhất định để ghi đè configurephương thức lấy WebSecurityđối tượng và ignoremẫu.

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

Và xóa dòng đó khỏi HttpSecurityphần. Điều này sẽ yêu cầu Spring Security bỏ qua URL này và không áp dụng bất kỳ bộ lọc nào cho chúng.


4
tệp này được viết bằng gì?
Jacob Zimmerman

3
@JacobZimmerman spring.io/blog/2013/07/03/… trình cấu hình cho lớp bảo mật web
Askar Ibragimov

1
Chỉ muốn thêm bạn phải mở rộng WebSecurityConfigurerAdapteroverrideđiều này methodtrong đó.
muasif80

19

Tôi có một cách tốt hơn:

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

3
Đoạn mã này được gọi ở đâu?
Viacheslav Shalamov

@ViacheslavShalamov Trong của bạn WebSecurityConfig extends WebSecurityConfigurerAdapter's configure(HttpSecurity http)phương pháp. Xem baeldung.com/java-config-spring-security
jAC

1
điều này là phổ biến nhất trên internet, thực sự đó là thực hành sai. nếu bạn cho phép tất cả, bạn có nghĩa là nó vẫn cần phải xác thực nhưng cuối cùng bạn đã cho phép. vậy tại sao chúng ta nên xác thực (ý tôi là các bộ lọc xác thực sẽ vẫn được kích hoạt) để có quyền truy cập đăng ký?
Chao

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

Hoặc với cấu hình Java:

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

Thay vì cũ:

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

cho điểm kinh nghiệm. tắt bảo mật cho trang đăng nhập:

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

9

Đây có thể không phải là câu trả lời đầy đủ cho câu hỏi của bạn, tuy nhiên nếu bạn đang tìm cách vô hiệu hóa tính năng bảo vệ csrf, bạn có thể làm:

@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());
    }

}

Tôi đã bao gồm cấu hình đầy đủ nhưng dòng quan trọng là:

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

2

Như @ M.Deinum đã viết câu trả lời.

Tôi đã thử với api /api/v1/signup. nó sẽ bỏ qua bộ lọc / bộ lọc tùy chỉnh nhưng một yêu cầu bổ sung được gọi bởi trình duyệt /favicon.ico, vì vậy, tôi cũng thêm nó vào web.ignoring () và nó hoạt động với tôi.

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

Có thể điều này không bắt buộc đối với câu hỏi trên.


2

Nếu bạn muốn bỏ qua nhiều điểm cuối API, bạn có thể sử dụng như sau:

 @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

Tôi phải đối mặt với cùng một vấn đề, đây là giải pháp: ( Giải thích )

@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.**
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.