Spring 安全 SAML OpenAM

Posted

技术标签:

【中文标题】Spring 安全 SAML OpenAM【英文标题】:Spring security SAML OpenAM 【发布时间】:2017-02-15 08:42:15 【问题描述】:

我正在尝试使用带有 angular2 的前端和带有 Spring Boot 的 REST 后端来开发 Web 应用程序。

我需要管理 3 种类型的身份验证: - 基本的登录名/密码匹配数据库 - ldap 认证 - sso 认证

当用户通过身份验证时,后端会生成一个 JWT 并发送给前端。所有请求的标头中都必须包含 jwt 才能与 REST 通信。

此时我的网络安全配置是:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableTransactionManagement
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter 

    private static final String LDAP_AUTHENTIFICATION = "ldap";
    private static final String SSO_AUTHENTIFICATION = "sso";

    @Autowired
    private DataBaseAuthentificationProvider authProvider;

    @Value("$ldap.provider.url")
    private String ldapProviderUrl;

    @Value("$ldap.user.dn.patterns")
    private String userDnPatterns;

    @Value("$authentification.type")
    private String authentificationType;

    public WebSecurityConfiguration() 
        /*
         * Ignores the default configuration, useless in our case (session
         * management, etc..)
         */
        super(true);
    

    /**
     * Configure AuthenticationManagerBuilder to use the specified
     * DetailsService.
     * 
     * @param auth
     *            the @link AuthenticationManagerBuilder to use
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 

        if (StringUtils.equals(authentificationType, LDAP_AUTHENTIFICATION))  // LDAP
            auth.ldapAuthentication().userDnPatterns(userDnPatterns).contextSource().url(ldapProviderUrl);
         else if (StringUtils.equals(authentificationType, SSO_AUTHENTIFICATION))  // SSO

         else  // Database
            auth.authenticationProvider(authProvider);
        

    

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception 
        /*
         * Overloaded to expose Authenticationmanager's bean created by
         * configure(AuthenticationManagerBuilder). This bean is used by the
         * AuthenticationController.
         */
        return super.authenticationManagerBean();
    

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception 

        /*
         * the secret key used to signe the JWT token is known exclusively by
         * the server. With Nimbus JOSE implementation, it must be at least 256
         * characters longs.
         */
        String secret = IOUtils.toString(getClass().getClassLoader().getResourceAsStream("secret.key"),
                Charset.defaultCharset());

        httpSecurity.addFilterAfter(jwtTokenAuthenticationFilter("/**", secret), ExceptionTranslationFilter.class)
                .addFilterBefore(new SimpleCORSFilter(), CorsFilter.class)
                /*
                 * Exception management is handled by the
                 * authenticationEntryPoint (for exceptions related to
                 * authentications) and by the AccessDeniedHandler (for
                 * exceptions related to access rights)
                 */
                .exceptionHandling().authenticationEntryPoint(new SecurityAuthenticationEntryPoint())
                .accessDeniedHandler(new RestAccessDeniedHandler()).and()
                /*
                 * anonymous() consider no authentication as being anonymous
                 * instead of null in the security context.
                 */
                .anonymous().and()
                /* No Http session is used to get the security context */
                .sessionManagement().sessionCreationPolicy(STATELESS).and().authorizeRequests()
                /*
                 * All access to the authentication service are permitted
                 * without authentication (actually as anonymous)
                 */
                .antMatchers("/auth/**").permitAll()
                /*
                 * All the other requests need an authentication. Role access is
                 * done on Methods using annotations like @PreAuthorize
                 */
                .anyRequest().authenticated().and().addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class).csrf()
                .csrfTokenRepository(csrfTokenRepository()).disable();
    

    private CsrfTokenRepository csrfTokenRepository() 
        HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
        repository.setHeaderName("X-XSRF-TOKEN"); // this is the name angular
        // uses by default.
        return repository;
    

    private JwtTokenAuthenticationFilter jwtTokenAuthenticationFilter(String path, String secret) 
        return new JwtTokenAuthenticationFilter(path, secret);
    

关键点是单点登录:

我想要的行为如下:

客户端请求受保护的 REST 资源:

如果用户已经被 OpenAM 登录 => 返回询问的资源 如果用户尚未登录 => 用户将被重定向到 OpenAM 并提供其 凭据 => 用户可以访问资源

首先,我在虚拟机上安装了 OpenAM,创建了一个 SAMLv2 Providers 并获取了我的 idp.xml。

我尝试使用https://github.com/vdenotaris/spring-boot-security-saml-sample 来添加sso 认证但失败了。

有人可以给我步骤以便将其集成到我的网络安全配置中吗?

谢谢!

【问题讨论】:

你的错误是什么?我最近建立了一个 OpenAM 服务器并经历了一些挫折,但最终设法让它工作(使用 OpenSAML) 没有错误我不明白如何在我的身份验证配置中集成 opnsaml 以获得 3 种身份验证类型。 您好,您的问题解决了吗?你能发表一些意见吗? 【参考方案1】:

我会坚持使用 JWT,而不是 SAML,它增加了复杂性而没有任何好处,有很多示例如何使用 JWT 保护 REST 服务,并且 openam 支持提供 JWT 令牌的 OIDC。

一些有用的链接:

OpenAM spring security integration

Springboot OIDC OpenAM

【讨论】:

以上是关于Spring 安全 SAML OpenAM的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 在本地环境中禁用 SAML 安全性

基于 SAML 响应在 Grails 中分配 Spring 安全角色

Spring SAML 安全证书缓存问题

OpenAM ITfoxtec Saml2 无效签名响应?

带有 Spring 会话的 Spring Security SAML

我可以在应用程序中同时实现 SAML 和基本 spring 安全性吗?