【问题标题】:How to disable spring security for particular url如何禁用特定网址的弹簧安全性
【发布时间】:2015-08-02 16:31:13
【问题描述】:

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

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

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

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

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

我的 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";
    }
}

我对spring完全陌生,请帮助我怎么做?

【问题讨论】:

标签: java spring spring-mvc spring-security


【解决方案1】:

当使用permitAll 时,它表示每个经过身份验证的用户,但是您禁用了匿名访问,因此这将不起作用。

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

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

并从HttpSecurity 部分中删除该行。这将告诉 Spring Security 忽略此 URL,并且不对它们应用任何过滤器。

【讨论】:

  • 这会写入什么文件?
  • @JacobZimmerman spring.io/blog/2013/07/03/… 网络安全类的配置器
  • 只是想添加你必须在其中扩展WebSecurityConfigurerAdapteroverride这个method
  • 这对我不起作用。即使按照所述添加web.ignoring.antMatchers(..),我也会收到此错误:org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
  • 那你还没有配置好,否则它会起作用。
【解决方案2】:

我有更好的办法:

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

【讨论】:

  • 这个 sn-p 应该在哪里调用?
  • @ViacheslavShalamov 在您的WebSecurityConfig extends WebSecurityConfigurerAdapterconfigure(HttpSecurity http) 方法中。见baeldung.com/java-config-spring-security
  • 这在互联网上最常见,实际上是错误的做法。如果你允许所有,你的意思是它仍然需要验证,但你最终允许它。那么我们为什么要对注册访问进行身份验证(我的意思是仍然会触发身份验证过滤器)?
【解决方案3】:
<http pattern="/resources/**" security="none"/>

或使用 Java 配置:

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

代替旧的:

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

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

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

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

      也许上述问题不需要。

      【讨论】:

        【解决方案6】:

        如果你想忽略多个 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);
            }
        

        【讨论】:

          【解决方案7】:

          我遇到了同样的问题,解决方法如下:解释

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

          【讨论】:

            猜你喜欢
            • 2012-06-05
            • 2019-03-03
            • 1970-01-01
            • 2017-12-02
            • 2019-11-27
            • 1970-01-01
            • 2012-07-27
            • 2020-05-19
            相关资源
            最近更新 更多