【问题标题】:Spring security SAML OpenAMSpring 安全 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 种身份验证类型。
  • 您好,您的问题解决了吗?你能发表一些意见吗?

标签: java spring-security single-sign-on openam


【解决方案1】:

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

一些有用的链接:

OpenAM spring security integration

Springboot OIDC OpenAM

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-02
    • 2013-07-12
    • 2015-05-19
    • 1970-01-01
    • 2019-06-25
    • 2016-01-25
    • 2014-07-04
    • 1970-01-01
    相关资源
    最近更新 更多