具有数据库角色的Spring Security SAML

时间:2016-03-22 17:45:41

标签: java spring spring-security spring-saml

我尝试将SAML SSO集成到现有的应用程序中,该应用程序将Spring Security与存储在MySQL数据库中的用户,组和角色/权限结合使用。应用程序当前使用<security:jdbc-user-service>从数据库中获取用户和角色。有问题的IDP仅提供唯一的用户名和电子邮件地址作为属性,因此应用程序仍然必须存储与每个用户本身相关联的组和角色(据我所知)。

因此,我尝试通过上下文配置和自定义jdbc-user-servicesamlAuthenticationProviderSAMLUserDetailsService挂钩来尝试同时使用SAML和数据库。

这是我applicationContext.xml的相关部分:                   

<bean id="samlAuthenticationProvider" class="org.springframework.security.saml.SAMLAuthenticationProvider">
    <property name="userDetails" ref="customUserDetailService" />
</bean>
<bean id="customUserDetailService" class="org.myapp.CustomUserDetailsService">
    <property name="jdbcUserService" ref="jdbcUserDetailService" />
</bean>

<bean id="jdbcUserDetailService" class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
    <property name="dataSource" ref="dataSource" />
    <property name="usersByUsernameQuery" value="select username,username as password,enabled from person where username=?" />
    <property name="authoritiesByUsernameQuery" value="select u.username, p.name as authorities 
                from person u, group g, group_permissions up, permission p 
                where u.group = g.id and g.id = up.group and up.permissions = p.id and  
                u.username=?" />
</bean>

这是CustomUserDetailsService

的相关部分
public class CustomUserDetailsService implements SAMLUserDetailsService {

    private JdbcDaoImpl jdbcUserService;

    @Override
    public Object loadUserBySAML(SAMLCredential credential) throws UsernameNotFoundException {

        UserDetails user = null;
        String username = credential.getAttributeAsString("urn:mace:dir:attribute-def:cn");

        try {
            user = jdbcUserService.loadUserByUsername(username);
        } catch (UsernameNotFoundException e) {
            System.out.println("User not found in DB");
            // TODO
        }

        return user;
    }

    @Autowired
    public void setJdbcUserService(JdbcDaoImpl jdbcUserService) {
        this.jdbcUserService = jdbcUserService;
    }

    public JdbcDaoImpl getJdbcUserService() {
        return jdbcUserService;
    }
}

我的问题是:以这种方式使用org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl是个好主意吗?

我认为从数据库中检索角色的官方Spring Security实现(JdbcDaoImpl)比我自己想出的更好,更灵活,更无错误。

我的第二个问题是:是否会使用select username, username as password以某种方式在应用中创建安全问题?

由于我的应用程序永远不会看到密码(因为用户只在IDP处输入密码),我必须将其替换为查询中的内容。我是否应该注意使用这个难以猜测的东西,或者用户详细信息中的密码是否仍未重复使用?

2 个答案:

答案 0 :(得分:1)

<强> 1。这是一个好主意和/或它的使用方式吗?

是的,您可以在spring中拥有自定义用户对象并填充用户详细信息。

2.会使用select username,username as password以某种方式在应用程序中创建安全问题吗?

不,Spring SAML并不期望用户密码存储在用户对象中(相反,saml响应将由spring验证)。 spring将仅验证用户名和权限。我建议您只在用户对象中设置用户名和授权机构。

答案 1 :(得分:0)

考虑如下图表:

SAML-based AuthN

它描述了基于SAML的身份验证过程的所有典型步骤。

  • 将要求受保护资源的用户从服务提供商(信赖方)重定向到第三方身份提供商。
  • 用户在身份提供商处执行身份验证(即提供用户名/密码,OTP,PIN码等)。
  • 如果身份验证成功,身份提供商会向服务提供商发回SAML信封。它包含存储在SAML断言中的用户的配置文件信息(名字,姓氏,电子邮件,电话号码,组织等),根据双方之间关于属性释放的协议。用户也被重定向回服务提供商。

此时,由于双方之间的信任关系,IdP保证用户身份。因为AuthN过程已完成,您不再需要密码了。 此时您通常需要的是管理资源访问控制的信息,因此是授权(AuthZ)。通常,使用角色模型(RBAC)执行AuthZ:

The user "jdoe" is authenticated.
The user "jdoe" has "StandardUser" as role.
The resource A is available only for "Administrator".
The user "jdoe" is not authorised to access to the resource A.

同样:

The user "jdoe" is authenticated.
The user "jdoe" has "StandardUser" as role.
The resource B is available only for "StandardUser".
The user "jdoe" is authorised to access to the resource B.

考虑到所有用户的角色都存储在本地数据库中,您必须检索执行数据访问的信息才能匹配身份和角色。

所以:

这是一个好主意和/或它的使用方式吗?

方法loadUserBySAML应该标识SAML断言中的数据引用的用户的本地帐户,并返回描述用户的UserDetails对象。此时,您还应根据其在应用程序域中的角色向特定用户授予适当的权限。 本地数据检索实现由您决定。您可以使用标准访问,对数据库执行直接查询,或者根据JPA规范(请参阅 Spring Data )实现现代数据访问模型,同时使用ORM。

使用选择用户名,用户名作为密码会以某种方式在应用中创建安全问题吗?

如前所述,由于您使用的是基于SAML的身份验证,因此无需在应用程序上执行用户凭据验证。 SSO实际上是为了不共享密码等关键信息而设计的。