我想創建一個主要提供使用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