当我尝试将Chrome浏览器的POSTMAN插件中的JSON有效负载发送到作为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() 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作为授权类型,并在POSTMAN中将JSON有效负载发送到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安全依赖性
org.springframework.security spring-security-config 3.2.3.RELEASE org.springframework.security spring-security-web 3.2.3.RELEASE
我在POSTMAN中发送身份验证凭据.但仍然为什么我得到上述例外.
您创建了一个springSecurityFilterChain
with WebSecurityConfigurerAdapter
,请参见Spring Security Reference:
第一步是创建我们的Spring Security Java配置。该配置将创建一个Servlet过滤器,称为Servlet过滤器,该过滤器
springSecurityFilterChain
负责应用程序中的所有安全性(保护应用程序URL,验证提交的用户名和密码,重定向到登录表单等)。
但是您没有使用它(它不在您的堆栈跟踪中)。
您必须注册springSecurityFilterChain
。如果您具有Servlet 3.0+环境,请参阅Spring Security Reference:
带有Spring MVC的AbstractSecurityWebApplicationInitializer
如果我们在应用程序的其他地方使用Spring,则可能已经有一个
WebApplicationInitializer
正在加载Spring Configuration的代码。如果我们使用以前的配置,将会得到一个错误。相反,我们应该在现有上注册Spring SecurityApplicationContext
。例如,如果我们使用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 ... }