【问题标题】:Spring Security: Rest endpoint is not found after securing with @SecuredSpring Security:使用@Secured 保护后未找到 Rest 端点
【发布时间】:2019-06-17 22:59:01
【问题描述】:

我正在尝试通过 Spring Security 的 @Secured 注释来保护 REST 端点。我的带有安全配置的主应用程序(Spring Boot App)和其余控制器位于不同的包和项目中。

主应用包:com.myapp.api.web

Rest 控制器包:com.myapp.api.rest

主应用程序:

@SpringBootApplication
@ComponentScan(basePackages = "com.myapp.api")
@EntityScan("com.myapp.api")
@RestController
public class ApiApplication extends SpringBootServletInitializer
{
public static void main(String[] args)
{
    SpringApplication.run(ApiApplication.class, args);
}

@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
{
    return application.sources(ApiApplication.class);
}

}

安全配置:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true, 
securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
private static final String USERS_CONFIG_FILE_NAME = "users.yml";

@Override
protected void configure(HttpSecurity http) throws Exception
{
    http
        .httpBasic()
        .and()
        .csrf().disable();

    http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}

@Bean
public PasswordEncoder passwordEncoder()
{
    return new BCryptPasswordEncoder();
}

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth,
    InMemoryUserDetailsManager inMemoryUserDetailsManager, PasswordEncoder passwordEncoder) throws Exception
{
    auth.userDetailsService(inMemoryUserDetailsManager).passwordEncoder(passwordEncoder);
}

@Bean
public InMemoryUserDetailsManager inMemoryUserDetailsManager() throws IOException
{
    return new InMemoryUserDetailsManager(
        PropertiesLoaderUtils.loadAllProperties(USERS_CONFIG_FILE_NAME, getClass().getClassLoader()));
}

}

休息控制器:

@RestController
public class RestController
{

private final RestService service;

@PostMapping("/rest/v1")
@Secured({"ROLE_ADMIN"})
public List<String> getStates(@RequestBody List<String> Ids)
{
    ...
}

只要我没有设置 securedEnabled = true,我的休息端点就可以工作。设置它 true 后,我收到 404 Not Found 作为响应消息。我已经对其进行了调试,发现 Spring Security 有时会在过滤器链中停止,并且请求永远不会到达控制器。

据我测试,只要其余控制器在不同的项目中,就会发生此错误。将其移至同一个项目后,它可以正常工作。

我的 Securityconfig 中是否缺少某些内容或可能是什么问题?

【问题讨论】:

  • 尝试检查 spring 是否在安全上下文中包含您的用户。 UserDetails userDetails = (UserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
  • ApiApplicationSecurityConfiguration 在哪里(包)?

标签: java spring rest spring-security


【解决方案1】:

我可以通过您的代码获取值,我只将 Password Encoder 更改为默认值并更改了 inMemoryAuthentication 。 我这样做是因为我没有您的文件“users.yml”如果您可以共享示例,我们将查看它,但下面是我的代码。我将所有逻辑保存在 2 个文件中只是为了验证。

配置类

package com.myapp.api.web.Api;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true, 
securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
private static final String USERS_CONFIG_FILE_NAME = "users.yml";

@Override
protected void configure(HttpSecurity http) throws Exception
{
    http
        .httpBasic()
        .and()
        .csrf().disable();

    http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Bean
public PasswordEncoder passwordEncoder() {
    return new PasswordEncoder() {
        @Override
        public String encode(CharSequence rawPassword) {
            return rawPassword.toString();
        }
        @Override
        public boolean matches(CharSequence rawPassword, String encodedPassword) {
            return rawPassword.toString().equals(encodedPassword);
        }
    };
}

@Override
protected void configure(AuthenticationManagerBuilder builder) throws Exception {
    builder.inMemoryAuthentication()
      .withUser("user").password("user").roles("USER")
      .and().withUser("admin").password("admin").roles("ADMIN");
}
/*
@Bean
public InMemoryUserDetailsManager inMemoryUserDetailsManager() throws IOException
{


    return new InMemoryUserDetailsManager(
        PropertiesLoaderUtils.loadAllProperties(USERS_CONFIG_FILE_NAME, getClass().getClassLoader()));
}*/
}

主类

package com.myapp.api.web.Api;

import java.util.List;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@ComponentScan(basePackages = "com.myapp.api")
@RestController
@SpringBootApplication
public class ApiApplication {

    public static void main(String[] args) {
        SpringApplication.run(ApiApplication.class, args);
    }
    @PostMapping("/rest/v1")
    @Secured({"ROLE_ADMIN"})
    public List<String> getStates(@RequestBody List<String> Ids)
    {
        return Ids;
       // ...
    }

}

【讨论】:

    猜你喜欢
    • 2016-03-04
    • 2019-06-19
    • 2014-07-29
    • 2014-02-21
    • 2017-05-27
    • 2016-08-13
    • 2016-10-18
    • 2014-12-06
    • 2018-08-11
    相关资源
    最近更新 更多