java AuthenticationCredentialsNotFoundException:在安全上下文中找不到身份验证对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/41710743/
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
AuthenticationCredentialsNotFoundException: An Authentication object was not found in the Security Context
提问by JavaDeveloper
I get the below error when I try to send JSON payload from POSTMAN plugin of chrome browser to controller exposed as REST URL - http://localhost:8080/services/acc/create
当我尝试将 JSON 有效负载从 chrome 浏览器的 POSTMAN 插件发送到作为 REST URL 公开的控制器时,出现以下错误 - http://localhost:8080/services/acc/create
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/services] threw exception [Request processing failed; nested exception is org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext] with root cause
org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:339)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:198)
at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:60)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655)
at com.webadvisors.controller.HotelRestController$$EnhancerBySpringCGLIB$$e9f80d9.createHotel(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
I selected BasicAuth as authorization type and entered username and password while sending JSON payload to REST URL in POSTMAN.
我选择 BasicAuth 作为授权类型并输入用户名和密码,同时将 JSON 有效负载发送到 POSTMAN 中的 REST URL。
1) Controller class
1) 控制器类
@RestController
public class AccountRestController {
@Autowired
private AccountService accountService;
@PreAuthorize("hasAnyRole('ADMINISTRATOR')")
@RequestMapping(value= "/acc/create", method=RequestMethod.POST)
public HotelDTO createHotel(@RequestBody AccountDTO accDTO) throws Exception{
return accountService.create(accDTO);
}
}
2) Security Configuration class
2)安全配置类
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
@ComponentScan(basePackages = "com.freelance", scopedProxy = ScopedProxyMode.INTERFACES)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("authenticationService")
private UserDetailsService userDetailsService;
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
auth.authenticationProvider(authenticationProvider());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/user/**").permitAll()
.anyRequest().fullyAuthenticated();
http.httpBasic();
http.csrf().disable();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}
}
3) Spring security dependencies
3)Spring安全依赖
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.2.3.RELEASE</version>
</dependency>
I am sending the authentication credentials in the POSTMAN. But still why am I getting the above exception.
我正在邮递员中发送身份验证凭据。但仍然为什么我会收到上述异常。
采纳答案by dur
You created a springSecurityFilterChain
with WebSecurityConfigurerAdapter
, see Spring Security Reference:
您创建了一个springSecurityFilterChain
with WebSecurityConfigurerAdapter
,请参阅Spring Security Reference:
The first step is to create our Spring Security Java Configuration. The configuration creates a Servlet Filter known as the
springSecurityFilterChain
which is responsible for all the security (protecting the application URLs, validating submitted username and passwords, redirecting to the log in form, etc) within your application.
第一步是创建我们的 Spring Security Java 配置。该配置创建了一个称为 的 Servlet 过滤器,
springSecurityFilterChain
它负责应用程序中的所有安全性(保护应用程序 URL、验证提交的用户名和密码、重定向到登录表单等)。
but you didn't use it (it is not in your stack trace).
但您没有使用它(它不在您的堆栈跟踪中)。
You have to register springSecurityFilterChain
. If you have a Servlet 3.0+ environment, see Spring Security Reference:
你必须注册springSecurityFilterChain
。如果您有 Servlet 3.0+ 环境,请参阅Spring Security Reference:
AbstractSecurityWebApplicationInitializer with Spring MVC
If we were using Spring elsewhere in our application we probably already had a
WebApplicationInitializer
that is loading our Spring Configuration. If we use the previous configuration we would get an error. Instead, we should register Spring Security with the existingApplicationContext
. For example, if we were using Spring MVC ourSecurityWebApplicationInitializer
would look something like the following:import org.springframework.security.web.context.*; public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer { }
This would simply only register the springSecurityFilterChain Filter for every URL in your application. After that we would ensure that
WebSecurityConfig
was loaded in our existing ApplicationInitializer. For example, if we were using Spring MVC it would be added in thegetRootConfigClasses()
public class MvcWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[] { WebSecurityConfig.class }; } // ... other overrides ... }
带有 Spring MVC 的 AbstractSecurityWebApplicationInitializer
如果我们在应用程序的其他地方使用 Spring,我们可能已经有一个
WebApplicationInitializer
正在加载我们的 Spring 配置。如果我们使用以前的配置,我们会得到一个错误。相反,我们应该使用现有的ApplicationContext
. 例如,如果我们使用 Spring MVC,我们SecurityWebApplicationInitializer
会看起来像下面这样:import org.springframework.security.web.context.*; public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer { }
这只会为应用程序中的每个 URL 注册 springSecurityFilterChain 过滤器。之后,我们将确保
WebSecurityConfig
已加载到我们现有的 ApplicationInitializer 中。例如,如果我们使用 Spring MVC,它将被添加到getRootConfigClasses()
public class MvcWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[] { WebSecurityConfig.class }; } // ... other overrides ... }