我尝试将SAML SSO集成到现有的应用程序中,该应用程序将Spring Security与存储在MySQL数据库中的用户,组和角色/权限结合使用。应用程序当前使用<security:jdbc-user-service>
从数据库中获取用户和角色。有问题的IDP仅提供唯一的用户名和电子邮件地址作为属性,因此应用程序仍然必须存储与每个用户本身相关联的组和角色(据我所知)。
因此,我尝试通过上下文配置和自定义jdbc-user-service
将samlAuthenticationProvider
与SAMLUserDetailsService
挂钩来尝试同时使用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处输入密码),我必须将其替换为查询中的内容。我是否应该注意使用这个难以猜测的东西,或者用户详细信息中的密码是否仍未重复使用?
答案 0 :(得分:1)
<强> 1。这是一个好主意和/或它的使用方式吗?
是的,您可以在spring中拥有自定义用户对象并填充用户详细信息。
2.会使用select username,username as password以某种方式在应用程序中创建安全问题吗?
不,Spring SAML并不期望用户密码存储在用户对象中(相反,saml响应将由spring验证)。 spring将仅验证用户名和权限。我建议您只在用户对象中设置用户名和授权机构。
答案 1 :(得分:0)
考虑如下图表:
它描述了基于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实际上是为了不共享密码等关键信息而设计的。