AuthenticationCredentialsNotFoundException:在安全上下文中找不到身份验证对象
Posted
技术标签:
【中文标题】AuthenticationCredentialsNotFoundException:在安全上下文中找不到身份验证对象【英文标题】:AuthenticationCredentialsNotFoundException: An Authentication object was not found in the Security Context 【发布时间】:2017-06-02 07:39:57 【问题描述】:当我尝试将 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)
我选择 BasicAuth 作为授权类型,并在将 JSON 有效负载发送到 POSTMAN 中的 REST URL 时输入了用户名和密码。
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) 安全配置类
@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 安全依赖项
<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>
我在 POSTMAN 中发送身份验证凭据。但是为什么我会得到上述异常。
【问题讨论】:
【参考方案1】:您使用WebSecurityConfigurerAdapter
创建了一个springSecurityFilterChain
,请参阅Spring Security Reference:
第一步是创建我们的 Spring Security Java 配置。该配置创建了一个称为
springSecurityFilterChain
的 Servlet 过滤器,它负责您的应用程序中的所有安全性(保护应用程序 URL、验证提交的用户名和密码、重定向到登录表单等)。
但你没有使用它(它不在你的堆栈跟踪中)。
您必须注册springSecurityFilterChain
。如果您有 Servlet 3.0+ 环境,请参阅Spring Security Reference:
AbstractSecurityWebApplicationInitializer 与 Spring MVC
如果我们在应用程序的其他地方使用 Spring,我们可能已经有一个
WebApplicationInitializer
正在加载我们的 Spring 配置。如果我们使用以前的配置,我们会得到一个错误。相反,我们应该使用现有的ApplicationContext
注册 Spring Security。例如,如果我们使用 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 ...
【讨论】:
以上是关于AuthenticationCredentialsNotFoundException:在安全上下文中找不到身份验证对象的主要内容,如果未能解决你的问题,请参考以下文章