簡體   English   中英

Spring Security - @PreAuthorize 返回 404

[英]Spring Security - @PreAuthorize returns 404

我在使用 Spring Method Security 時遇到了一個奇怪的問題, @PreAuthorize("hasRole('MODERATOR')")

如果用戶嘗試訪問需要“MODERATOR”角色的控制器,則返回資源,一切正常(如果用戶實際上具有該角色)。 但是,如果用戶沒有此角色,則服務器返回 404 - Not Found。 這很奇怪,因為我預計服務器會返回其他內容,也許是 403 Forbidden? 知道為什么會發生這種情況嗎? 這是我的安全配置:

@EnableWebSecurity
@Order(2)
public class WebSecurity extends WebSecurityConfigurerAdapter {

    private final UserDetailsService userDetailsService;
    private final BCryptPasswordEncoder bCryptPasswordEncoder;

    public WebSecurity(UserDetailsService userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder) {
        super();
        this.userDetailsService = userDetailsService;
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .antMatcher("/api/**")
                .cors()
                .and()
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .addFilter(new JWTAuthenticationFilter(authenticationManager()))
                .addFilter(new JWTAuthorizationFilter(authenticationManager()))
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); 
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
    }

    @Bean 
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.applyPermitDefaultValues();
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }      

}

和我的控制器:

@GetMapping
@PreAuthorize("hasRole('MODERATOR')")
public List<ApplicationUser> getAllUsers(HttpServletRequest request) {
    try (final ConnectionResource connectionResource = connectionFactory.create(); final UserDAO dao = new UserDAO()) {
        dao.setEm(connectionResource.em);
        return dao.getAllUsers();
    } catch (Exception ex) {
        Logger.getLogger(UserController.class.getName()).log(Level.SEVERE, "unable to get all users", ex);
        return null;
    }
}

謝謝!

可以在注釋@EnableGlobalMethodSecurity(prePostEnabled=true)的幫助下啟用全局方法安全性。 這個和@Preauthorize的組合將為您的控制器創建一個新的代理,它會丟失請求映射(在您的情況下為 GetMapping),這將導致 404 異常。

要處理此問題,您可以使用@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)

Spring 文檔中的帶注釋控制器

一個相關的 Github 問題

我們需要為使用 @PreAuthorize 注釋啟用全局方法安全性。 例如https://dzone.com/articles/securing-spring-data-rest-with-preauthorize

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
@Order(2)
public class WebSecurity extends WebSecurityConfigurerAdapter {
..............
}

以下是我執行此操作的代碼:-

 @Override
protected void configure(HttpSecurity http) throws Exception{
    http.authorizeRequests()
    .antMatchers(HttpMethod.POST,"/api/2.0/login/**").permitAll()
    .anyRequest().authenticated()
    .and().exceptionHandling().authenticationEntryPoint(unauthorizedEntryPoint())
    .and()  
    .addFilterBefore()
}


@Bean
public AuthenticationEntryPoint unauthorizedEntryPoint() {
    return new RestAuthenticationEntryPoint();
}


public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint{
private static Logger logger = Logger.getLogger(RestAuthenticationEntryPoint.class);

public RestAuthenticationEntryPoint() {
    super();
}

@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
        AuthenticationException authException) throws IOException, ServletException {
    logger.info("Inside Rest Authentication entry Points");
    String error="{ \"status\":\"FAILURE\",\"error\":{\"code\":\"401\",\"message\":\""+authException.getMessage()+"\"} }";
    HttpServletResponse httpResponse = (HttpServletResponse) response;
    httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    httpResponse.setContentType("application/json");

    if(authException instanceof BadCredentialsException){
        httpResponse.getOutputStream().println("{ \"Bad credential\": \"" + authException.getMessage() + "\" }");
    }
    if(authException instanceof AuthenticationCredentialsNotFoundException){
        logger.info("Inside AuthenticationCredentialsNotFoundException");
        error="{ \"status\":\"FAILURE\",\"error\":{\"code\":\""+SecurityExceptions.TOKEN_EXPIRED+"\",\"message\":\""+SecurityExceptions.TOKEN_EXPIRED_MESSAGE+"\"} }";
    }
    httpResponse.getOutputStream().println(error);
}

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM