我想创建一个主要提供使用Spring的REST API的webapp,并且正在尝试配置安全性方面。春季安全 - 基于令牌的API认证和用户/密码认证
我想实现这种模式:https://developers.google.com/accounts/docs/MobileApps(谷歌已经完全改变了该网页,所以不再有意义 - 看,我指的是这里的页面:http://web.archive.org/web/20130822184827/https://developers.google.com/accounts/docs/MobileApps)
这是我需要accompish:
- Web App有与通常弹簧用户名/密码认证工作的简单登录/注册表单
- REST API(与DAO /的AuthenticationManager/UserDetailsService的等做过这种类型的东西)无状态会话的端点和e非常请求基于与请求一起提供的令牌进行验证
(例如,用户登录/签约使用正常的形式,web应用程序提供的令牌安全cookie,然后可以在下面的API请求中使用)
我有如下一个正常的身份验证设置:
@Override protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/resources/**").permitAll()
.antMatchers("/mobile/app/sign-up").permitAll()
.antMatchers("/v1/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/")
.loginProcessingUrl("/loginprocess")
.failureUrl("/?loginFailure=true")
.permitAll();
}
我想加入一个pre-auth过滤器,它检查请求中的令牌,然后设置安全上下文(这是否意味着正常的后续认证会被跳过?),但是,超出正常用户/密码我没有做太多基于令牌的安全性,但基于其他一些例子,我想出了以下内容:
Security Con图:
@Override protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.addFilter(restAuthenticationFilter())
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.exceptionHandling().authenticationEntryPoint(new Http403ForbiddenEntryPoint()).and()
.antMatcher("/v1/**")
.authorizeRequests()
.antMatchers("/resources/**").permitAll()
.antMatchers("/mobile/app/sign-up").permitAll()
.antMatchers("/v1/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/")
.loginProcessingUrl("/loginprocess")
.failureUrl("/?loginFailure=true")
.permitAll();
}
我自其他过滤器:
public class RestAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public RestAuthenticationFilter(String defaultFilterProcessesUrl) {
super(defaultFilterProcessesUrl);
}
private final String HEADER_SECURITY_TOKEN = "X-Token";
private String token = "";
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
this.token = request.getHeader(HEADER_SECURITY_TOKEN);
//If we have already applied this filter - not sure how that would happen? - then just continue chain
if (request.getAttribute(FILTER_APPLIED) != null) {
chain.doFilter(request, response);
return;
}
//Now mark request as completing this filter
request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
//Attempt to authenticate
Authentication authResult;
authResult = attemptAuthentication(request, response);
if (authResult == null) {
unsuccessfulAuthentication(request, response, new LockedException("Forbidden"));
} else {
successfulAuthentication(request, response, chain, authResult);
}
}
/**
* Attempt to authenticate request - basically just pass over to another method to authenticate request headers
*/
@Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
AbstractAuthenticationToken userAuthenticationToken = authUserByToken();
if(userAuthenticationToken == null) throw new AuthenticationServiceException(MessageFormat.format("Error | {0}", "Bad Token"));
return userAuthenticationToken;
}
/**
* authenticate the user based on token, mobile app secret & user agent
* @return
*/
private AbstractAuthenticationToken authUserByToken() {
AbstractAuthenticationToken authToken = null;
try {
// TODO - just return null - always fail auth just to test spring setup ok
return null;
} catch (Exception e) {
logger.error("Authenticate user by token error: ", e);
}
return authToken;
}
上面实际上导致错误应用程序启动时说:authenticationManager must be specified
谁能告诉我如何更好地做到这一点 - 是pre_auth过滤器最好的方法来做到这一点?
编辑
我写了什么,我发现,我如何与Spring的安全性(包括代码)实现标准的token(没有的OAuth)
Overview of the problem and approach/solution
做到了Implementing the solution with Spring-security
希望它可以帮助别人..
我会在自定义实现上推荐[Spring Security OAuth(2)](http://projects.spring.io/spring-security-oauth/)。恕我直言,我会尽量避免实施自定义解决方案。大多数时候它很容易出错并且不安全。 特别是如果您使用的是Spring MVC,则可以将Spring Security和Spring Security OAuth(2) 视为基于令牌的身份验证流程的有效替代方案。 –
我原本计划使用OAuth2来实现安全性 - 但是质疑API计划只被我正在构建的应用程序使用(例如没有其他计划的客户端/消费者等),然后我看到上面的链接:https ://developers.google.com/accounts/docs/MobileApps与Google推荐了上述方法,另外对于单个客户我不知道OAuth2是否会过度杀伤。看到我关于安全性的以前的问题:http://stackoverflow.com/q/21461223/258813 – rhinds
我也看着这样的实现:http://www.thebuzzmedia.com/designing-a-secure-rest-api- without-oauth-authentication/- 但这非常接近双腿OAuth 1模式 – rhinds