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

新手上路,请多包涵

我知道保护 REST API 是一个被广泛评论的话题,但我无法创建满足我的标准的小型原型(我需要确认这些标准是否切合实际)。如何保护资源以及如何使用 Spring 安全性有很多选择,我需要澄清我的需求是否切合实际。

我的要求

  • 基于令牌的身份验证器 - 用户将提供其凭据并获得唯一且有时间限制的访问令牌。我想在我自己的实现中管理令牌创建、检查有效性和到期时间。
  • 一些 REST 资源将是公开的——根本不需要身份验证,
  • 某些资源仅供具有管理员权限的用户访问,
  • 其他资源将在所有用户授权后访问。
  • 我不想使用基本身份验证
  • Java 代码配置(非 XML)

当前状态

我的 REST API 运行良好,但现在我需要保护它。当我在寻找解决方案时,我创建了一个 javax.servlet.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 不能按我的需要工作,因为通过 @ControllerAdvice 使用 Spring servlet dispatcher

我需要的

我想知道这些标准是否切合实际并获得任何帮助,如何开始使用 Spring Security 保护 REST API。我阅读了许多教程(例如 Spring Data REST + Spring Security ),但所有教程都在非常基本的配置中工作——用户 及其凭据存储 在配置中的内存中,我需要使用 DBMS 并创建自己的身份验证器。

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

原文由 Artegon 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 496
2 个回答

基于令牌的身份验证——用户将提供其凭据并获得唯一且有时间限制的访问令牌。我想在我自己的实现中管理令牌创建、检查有效性和到期时间。

实际上,对令牌 Auth 使用过滤器 - 在这种情况下最好的方法

最终,您可以通过 Spring Data 创建 CRUD 来管理 Token 的属性,如过期等。

这是我的令牌过滤器:http: //pastebin.com/13WWpLq2

和令牌服务实现

http://pastebin.com/dUYM555E

一些 REST 资源将是公开的——根本不需要身份验证

这不是问题,您可以像这样通过 Spring 安全配置管理您的资源: .antMatchers("/rest/blabla/**").permitAll()

某些资源仅供具有管理员权限的用户访问,

看看 @Secured 类注释。例子:

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

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

回到 Spring Security 配置,你可以这样配置你的 url:

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

我不想使用基本身份验证

是的,通过令牌过滤器,您的用户将通过身份验证。

Java 代码配置(非 XML)

回到上面的话,看 @EnableWebSecurity 。你的班级将是:

 @Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {}

您必须重写 配置 方法。下面的代码,仅作为示例,如何配置匹配器。它来自另一个项目。

     @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();
}

原文由 Oleksandr Loushkin 发布,翻译遵循 CC BY-SA 3.0 许可协议

Spring Security 对于为 REST URL 提供身份验证和授权也非常有用。我们无需指定任何自定义实现。

首先,您需要在安全配置中将入口点引用指定为 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 键。这基本上用于识别用户的身份验证。通常 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"/>

“授权”是提交传入请求的关键。它包含所需用户的身份验证信息。您还需要配置 PreAuthenticatedAuthenticationProvider 以满足我们的要求。

    <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>

此代码将用于通过身份验证和授权保护 REST url,无需任何自定义实现。

有关完整代码,请找到以下链接:

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

原文由 Nalla Srinivas 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题