java Spring security 401未经授权在不安全的端点上

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41085983/
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-11-03 05:40:30  来源:igfitidea点击:

Spring security 401 Unauthorized on not secured endpoint

javaspringspring-bootspring-securitypostman

提问by Samuel Fraga Mateos

I'm trying to configure Spring Security on a Spring Boot application as follows:

我正在尝试在 Spring Boot 应用程序上配置 Spring Security,如下所示:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private RestAuthenticationEntryPoint unauthorizedHandler;

@Bean
public JwtAuthenticationFilter authenticationTokenFilterBean() throws Exception {
    JwtAuthenticationFilter authenticationTokenFilter = new JwtAuthenticationFilter();
    authenticationTokenFilter.setAuthenticationManager(authenticationManagerBean());
    return authenticationTokenFilter;
}

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {

    //@formatter:off
     httpSecurity
      .csrf()
        .disable()
      .exceptionHandling()
        .authenticationEntryPoint(this.unauthorizedHandler)
        .and()
      .sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
      .authorizeRequests()
        .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
        .antMatchers("/login", "/singup", "/subscribers").permitAll()
        .anyRequest().authenticated();

        // Custom JWT based security filter 
    httpSecurity            
        .addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);   

    //@formatter:on

}
}

My unauthorizedHandler is:

我的未授权处理程序是:

public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {

private static final Logger LOGGER = LoggerFactory.getLogger(RestAuthenticationEntryPoint.class);

@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
        AuthenticationException authException) throws IOException, ServletException {
    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}

}

Finally, the REST controller for /subscribers is:

最后,/subscribers 的 REST 控制器是:

@RestController
public class SubscriberRestController {

@Autowired
ISubscribersService subscribersService;

@RequestMapping(value = RequestMappingConstants.SUBSCRIBERS, method = RequestMethod.GET)
@ResponseBody
public Number subscriberCount() {

    return subscribersService.subscribersCount();
}

@RequestMapping(value = RequestMappingConstants.SUBSCRIBERS, method = RequestMethod.POST)
public String subscriberPost(@RequestBody SubscriberDocument subscriberDocument) {

    return subscribersService.subscribersInsert(subscriberDocument);
}

@RequestMapping(value = "/test", method = RequestMethod.GET)
public String test() {

    return "This is a test";
}

}

I use postman to test endpoints and when I do a POST to "localhost:8080/subscribers", I get:

我使用邮递员来测试端点,当我对“localhost:8080/subscribers”执行 POST 时,我得到:

Postman result

邮递员结果

I want to have opened endpoints (/subscribers) without any security control or credentials check, endpoints for singup and login and secured endpoints for authenticated users.

我想在没有任何安全控制或凭据检查的情况下打开端点(/订阅者)、用于注册和登录的端点以及经过身份验证的用户的安全端点。

Thanks! :)

谢谢!:)

采纳答案by Samuel Fraga Mateos

Spring Boot was not applying the configuration because couldn't find it. On Application.javaconfig package was not included with @ComponentScananotation.

Spring Boot 没有应用配置,因为找不到它。在Application.java配置包没有包含在@ComponentScan注释中。

回答by Guru Cse

You need to add the following to your configure method /error is the default fall back when error occurs to the application due to any exception and it is secured by default.

您需要将以下内容添加到您的配置方法中 /error 是当应用程序由于任何异常而发生错误时的默认回退,并且默认情况下是安全的。

protected void configure(HttpSecurity httpSecurity) throws Exception {
//disable CRSF
httpSecurity
        //no authentication needed for these context paths
        .authorizeRequests()
        .antMatchers("/error").permitAll()
        .antMatchers("/error/**").permitAll()
        .antMatchers("/your Urls that dosen't need security/**").permitAll()

Also the below code snippet

还有下面的代码片段

     @Override
       public void configure(WebSecurity webSecurity) throws Exception
         {
          webSecurity
          .ignoring()
           // All of Spring Security will ignore the requests
           .antMatchers("/error/**")
          }  

Now you will not get 401 and get 500 exception with details when an exception occurred for permitAll Urls

现在,当 permitAll Urls 发生异常时,您将不会获得 401 和 500 异常以及详细信息

回答by dikkini

After some researching, here is solution:

经过一番研究,这里是解决方案:

@SpringBootApplication(exclude = {SecurityAutoConfiguration.class })
@ComponentScan(basePackages = { PackageConstants.PACKAGE_CONTROLLERS_REST, PackageConstants.PACKAGE_SERVICES,
        PackageConstants.PACKAGE_SERVICES_IMPL, PackageConstants.PACKAGE_MONGO_REPOSITORIES,
        PackageConstants.PACKAGE_MONGO_REPOSITORIES_IMPL, PackageConstants.PACKAGE_UTILS })
public class Application {

    // Clase principal que se ejecuta en el bootrun

    public static void main(String[] args) {

        SpringApplication.run(Application.class, args);
    }
}

Main line is @SpringBootApplication(exclude = {SecurityAutoConfiguration.class })it tells not use Spring Boot Security AutoConfiguration configuration. It is not full answer, because now you have to tell Spring user your Spring Security configuration class. Also i advice you to create Initializer class with init Root Config Classes, ApplicationConfiguration using and refuse to use SpringBoot applications. Something like this:

主线是@SpringBootApplication(exclude = {SecurityAutoConfiguration.class })它告诉不要使用 Spring Boot Security AutoConfiguration 配置。这不是完整的答案,因为现在您必须告诉 Spring 用户您的 Spring Security 配置类。此外,我建议您使用 init Root Config Classes 创建 Initializer 类,ApplicationConfiguration 使用并拒绝使用 SpringBoot 应用程序。像这样的东西:

ApplicationConfig:

应用配置:

@Configuration
@EnableWebMvc
@ComponentScan("com.trueport.*")
@PropertySource("classpath:app.properties")
public class ApplicationConfig extends WebMvcConfigurerAdapter {
    ....
}

ApplicationSecurityConfig:

应用程序安全配置:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter {
    ....
}

Initializer:

初始化程序:

public class Initializer implements WebApplicationInitializer {

    private static final String DISPATCHER_SERVLET_NAME = "dispatcher";

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ....
        DispatcherServlet dispatcherServlet = new DispatcherServlet(ctx);
        dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
        ctx.register(ApplicationConfig.class);
        ServletRegistration.Dynamic servlet =     servletContext.addServlet(DISPATCHER_SERVLET_NAME,
            dispatcherServlet);
        servlet.addMapping("/");
        servlet.setLoadOnStartup(1);
        servlet.setAsyncSupported(true);
    }
}