如何使用Spring Boot和Spring Security来保护REST API?

我知道保护REST API是广泛评论的主题,但我无法创build一个满足我的标准的小原型(我需要确认这些标准是否现实)。 有如此多的select如何保护资源,以及如何与春季安全工作,我需要澄清,如果我的需求是现实的。

我的要求

  • 基于令牌的身份validation器 – 用户将提供其凭据并获取唯一且有时间限制的访问令牌。 我想pipe理令牌创build,检查有效性,在我自己的执行到期。
  • 一些REST资源将被公开 – 完全不需要authentication,
  • 有些资源只能用于拥有pipe理员权限的用户,
  • 其他资源将在所有用户授权后可访问。
  • 我不想使用基本身份validation
  • Java代码configuration(不是XML)

当前状态

我的REST API工作得很好,但现在我需要保护它。 当我正在寻找解决scheme时,我创build了一个javax.servlet.Filterfilter:

  @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; String accessToken = request.getHeader(AUTHORIZATION_TOKEN); Account account = accountDao.find(accessToken); if (account == null) { throw new UnauthorizedException(); } chain.doFilter(req, res); } 

但是这个javax.servlet.filters解决scheme不能正常工作,因为通过@ControllerAdvice和Spring servlet dispatcher处理exception是个问题。

我需要的

我想知道,如果这些标准是现实的,并得到任何帮助,如何开始与Spring安全性保护REST API。 我阅读了许多教程(例如Spring Data REST + Spring Security ),但都是以非常基本的configuration工作 – 拥有凭证的用户在configuration中存储在内存中,我需要使用DBMS并创build自己的身份validation器。

请给我一些想法如何开始。

基于令牌的身份validation – 用户将提供其凭据并获得唯一且有时间限制的访问令牌。 我想pipe理令牌创build,检查有效性,在我自己的执行到期。

其实,在这种情况下使用filter进行令牌validation – 最好的方法

最后,你可以通过Spring Data创buildCRUD来pipe理Token的属性,比如过期等等。

这是我的令牌filter: http : //pastebin.com/13WWpLq2

和令牌服务实现

http://pastebin.com/dUYM555E

一些REST资源将被公开 – 根本不需要authentication

这不是一个问题,你可以通过像这样的Spring安全configuration来pipe理你的资源: .antMatchers("/rest/blabla/**").permitAll()

有些资源只能用于拥有pipe理员权限的用户,

看看@Secured注解类。 例:

 @Controller @RequestMapping(value = "/adminservice") @Secured("ROLE_ADMIN") public class AdminServiceController { 

其他资源将在所有用户授权后可访问。

回到Spring Securityconfiguration,你可以像这样configuration你的url:

  http .authorizeRequests() .antMatchers("/openforall/**").permitAll() .antMatchers("/alsoopen/**").permitAll() .anyRequest().authenticated() 

我不想使用基本身份validation

是的,通过令牌filter,您的用户将被authentication。

Java代码configuration(不是XML)

回到上面的话,看看@EnableWebSecurity 。 你的课程将是:

 @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter {} 

你必须重写configure方法。 下面的代码,例如,如何configuration匹配器。 来自另一个项目。

  @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/assets/**").permitAll() .anyRequest().authenticated() .and() .formLogin() .usernameParameter("j_username") .passwordParameter("j_password") .loginPage("/login") .defaultSuccessUrl("/", true) .successHandler(customAuthenticationSuccessHandler) .permitAll() .and() .logout() .logoutUrl("/logout") .invalidateHttpSession(true) .logoutSuccessUrl("/") .deleteCookies("JSESSIONID") .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .and() .csrf(); } 

Spring安全性对于为REST URL提供authentication和授权也非常有用。 我们不需要指定任何自定义的实现。

首先,您需要在安全configuration中指定入口点引用restAuthenticationEntryPoint,如下所示。

  <security:http pattern="/api/**" entry-point-ref="restAuthenticationEntryPoint" use-expressions="true" auto-config="true" create-session="stateless" > <security:intercept-url pattern="/api/userList" access="hasRole('ROLE_USER')"/> <security:intercept-url pattern="/api/managerList" access="hasRole('ROLE_ADMIN')"/> <security:custom-filter ref="preAuthFilter" position="PRE_AUTH_FILTER"/> </security:http> 

restAuthenticationEntryPoint的实现可能如下。

  @Component public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint { public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException ) throws IOException { response.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized" ); } } 

在此之后,您需要指定RequestHeaderAuthenticationFilter。 它包含RequestHeader键。 这基本上用于识别用户的authentication。 通常RequestHeader在进行REST调用的同时携带这些信息。 例如考虑下面的代码

  <bean id="preAuthFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter"> <property name="principalRequestHeader" value="Authorization"/> <property name="authenticationManager" ref="authenticationManager" /> </bean> 

这里,

 <property name="principalRequestHeader" value="Authorization"/> 

“授权”是传入请求的关键。 它拥有所需的用户身份validation信息。 您还需要configurationPreAuthenticatedAuthenticationProvider以满足我们的要求。

  <bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider"> <property name="preAuthenticatedUserDetailsService"> <bean id="userDetailsServiceWrapper" class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper"> <property name="userDetailsService" ref="authenticationService"/> </bean> </property> </bean> 

这段代码将用于通过身份validation和授权来保护REST URL,而不需要任何自定义的实现。

完整的代码,请find下面的链接:

https://github.com/srinivas1918/spring-rest-security

我也search了很长时间。我正在做一个类似的项目。我发现Spring有一个通过redis实现会话的模块。 它看起来容易和有用。 我也将添加到我的项目。 可以帮助:

http://docs.spring.io/spring-session/docs/1.2.1.BUILD-SNAPSHOT/reference/html5/guides/rest.html

validationREST API有两种方法

1 – 使用在application.properties文件中设置的默认用户名和密码进行基本身份validation

基本authentication

2 – 使用实际的用户名和密码使用数据库(userDetailsS​​ervice)进行身份validation

高级authentication