我正在使用Spring Boot开发Spring REST应用程序。我正在使用角度JS客户端来使用Spring REST API。
我正在使用的堆栈是:
Spring Boot 1.4.2 , Spring Security , Angular JS , Tomcat 8
我的问题是:
1)登录时,用户会成功通过身份验证。自定义身份验证成功处理程序返回200状态代码。
2)认证成功后,当clint发送另一个请求来访问一个已获取的资源时,HttpSession为NULL
3)当SecurityContextPersistenceFilter
尝试从SecurityContext
检索HttpSession
时,它将返回为null并且
并且服务器再次向/login
资源发送请求
4)所以我的问题是:
1)为什么第二个请求的httpsesion为空?
2)我观察到Spring安全性在第一次成功验证后返回JSESSIONID
作为cookie。
3)但之后,客户端不会在请求中发送此JSESSIONID
,因此第二个请求不会在同一个会话中。
4)如果是这种情况,如果SecurityContext
未建立,将如何检索SESSION
?
请帮忙,因为我无法继续
编辑1:
我在弹簧安全性提供的内存用户中使用默认值。我的安全配置如下:
@Configuration
@EnableWebSecurity
@ComponentScan({"com.atul.security"})
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
private RESTAuthenticationSuccessHandler authenticationSuccessHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin().successHandler(authenticationSuccessHandler)
.and()
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS,"/*").permitAll()
.antMatchers("/index.html", "/home.html", "/login.html", "/").permitAll()
.anyRequest().authenticated()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
我作为经过身份验证的用户获得了以下用户:
org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc:
Principal: anonymousUser; Credentials: [PROTECTED];
Authenticated: true;
Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364:
RemoteIpAddress: 0:0:0:0:0:0:0:1;
SessionId: null;
Granted Authorities: ROLE_ANONYMOUS
请求现在失败:AbstractSecurityInterceptor
:AccessDecisionVoter
为authenticated
表达式返回false并抛出访问被拒绝的异常
答案 0 :(得分:1)
没有会话休息,因为RESTFUL服务不维护状态,读取此堆栈溢出帖子:
Do sessions really violate RESTfulness?
如果您想知道如何正确构建基于Spring的Spring安全服务,请查看本教程:
http://www.baeldung.com/securing-a-restful-web-service-with-spring-security
希望这会有所帮助。
您正在使用formLogin security ,这意味着您需要添加某种数据存储来对其进行身份验证。
以下是spring文档中内存数据存储的示例:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public UserDetailsService userDetailsService() throws Exception {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("user").password("password").roles("USER").build());
manager.createUser(User.withUsername("admin").password("password").roles("USER","ADMIN").build());
return manager;
}
}
根据此示例,您假设使用用户名和密码
成功进行身份验证您正尝试将angularJS作为前端技术应用安全性,这是一个很好的教程,如何实现这一点,我已经在我的项目中实现了它,这里是链接:
https://spring.io/guides/tutorials/spring-security-and-angular-js/
对于初学者,您需要使用httpBasic而非formLogin作为安全身份验证方法。
答案 1 :(得分:0)
长时间敲打头后,我终于找到了解决办法。
步骤是:
1)基于表单的登录需要建立会话。验证成功后,服务器会发送Set-Cookie:JSESSIONID=3974317C6DE34865B6726FCFD4C98C08; Path=/springbootrest; HttpOnly
标头作为响应。
2)浏览器必须在每个请求中发送此标头,否则将不会建立会话并且身份验证将失败
3)但是由于我使用CORS
(我的服务器和ui app驻留在本地系统上的不同端口上),浏览器未在请求中发送Cookie:JSESSIONID=3974317C6DE34865B6726FCFD4C98C08
未通过身份验证。
4)在浏览器开始在请求中发送标题之后,我必须在我的角度js客户端中添加以下行$httpProvider.defaults.withCredentials = true;
。
5)在服务器端,我必须在CORSFilter中添加以下代码。
response.setHeader("Access-Control-Allow-Credentials","true");
response.setHeader("Access-Control-Allow-Origin", "http://localhost:8186");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, WWW-Authenticate, Authorization, Origin, Content-Type, Version");
response.setHeader("Access-Control-Expose-Headers", "X-Requested-With, WWW-Authenticate, Authorization, Origin, Content-Type");
final HttpServletRequest request = (HttpServletRequest) req;
if("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}