如何使用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.Filter
filter:
@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
和令牌服务实现
一些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下面的链接:
我也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 – 使用实际的用户名和密码使用数据库(userDetailsService)进行身份validation
高级authentication