Java 如何禁用特定 url 的 spring 安全

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30366405/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 09:29:53  来源:igfitidea点击:

How to disable spring security for particular url

javaspringspring-mvcspring-security

提问by Prabjot Singh

I am using stateless spring security,but in case of signup i want to disable spring security.I disabled using

我正在使用无状态 spring 安全性,但在注册的情况下,我想禁用 spring 安全性。我禁用了使用

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

but it is not working,i am getting error below:

但它不起作用,我收到以下错误:

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

I think this means spring security filters are working

我认为这意味着 spring 安全过滤器正在工作

My url's order always will be "/api/v1"

我的网址的顺序总是“/api/v1”

My spring config is

我的弹簧配置是

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

My authentication filter is

我的身份验证过滤器是

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

My controller is

我的控制器是

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

I am totally new to spring,please help me how to do it ?

我对春天完全陌生,请帮我怎么做?

采纳答案by M. Deinum

When using permitAllit means every authenticated user, however you disabled anonymous access so that won't work.

使用permitAll它时意味着每个经过身份验证的用户,但是您禁用了匿名访问,因此无法正常工作。

What you want is to ignore certain URLs for this override the configuremethod that takes WebSecurityobject and ignorethe pattern.

您想要的是忽略某些 URL 以覆盖configure采用WebSecurity对象和ignore模式的方法。

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

And remove that line from the HttpSecuritypart. This will tell Spring Security to ignore this URL and don't apply any filters to them.

并从HttpSecurity零件上移除那条线。这将告诉 Spring Security 忽略此 URL 并且不对它们应用任何过滤器。

回答by Sagar Bhandari

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

Or with Java configuration:

或者使用 Java 配置:

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

Instead of the old:

而不是旧的:

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

for exp . disable security for a login page :

对于 exp 。禁用登录页面的安全性:

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

回答by javajoker

I have a better way:

我有一个更好的方法:

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

回答by Tomasz Mularczyk

This may be not the full answer to your question, however if you are looking for way to disable csrf protection you can do:

这可能不是您问题的完整答案,但是如果您正在寻找禁用 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());
    }

}

I have included full configuration but the key line is:

我已经包含了完整的配置,但关键是:

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

回答by eigenharsha

As @M.Deinum already wrote the answer.

因为@M.Deinum 已经写好了答案。

I tried with api /api/v1/signup. it will bypass the filter/custom filter but an additional request invoked by the browser for /favicon.ico, so, I add this also in web.ignoring() and it works for me.

我试过 api /api/v1/signup。它将绕过过滤器/自定义过滤器,但浏览器调用了一个额外的请求/favicon.ico,因此,我也在 web.ignoring() 中添加了它,它对我有用。

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

Maybe this is not required for the above question.

也许这不是上述问题所必需的。

回答by vishwaraj

If you want to ignore multiple API endpoints you can use as follow:

如果你想忽略多个 API 端点,你可以使用如下:

web.ignoring().antMatchers("/api/v1/authenticate", "/signup");

回答by shubham1js

I faced the same problem here's the solution:(Explained)

我面临着同样的问题,这里的解决方案:解释

@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.**
}