【问题标题】:Integrating Spring Security with SiteMinder将 Spring Security 与 SiteMinder 集成
【发布时间】:2014-05-22 00:50:48
【问题描述】:

如何将 Spring Security 与 SiteMinder 集成以接收用户和角色?

我有一个带有 Spring Security 'in-memory' 的项目设置,我想使用转换它来接受带有用户和角色的 SiteMinder 标头。如果 SiteMinder 将发送用户的角色 (ROLE_READ,ROLE_WRITE) 并让服务层授予访问权限。如何将内存转换为使用 SiteMinder?

内存中用户角色

内存中的用户和角色列表

<authentication-manager>
    <authentication-provider>
        <user-service>
            <user name="test" password="test" authorities="ROLE_READ" />
            <user name="admin" password="admin" authorities="ROLE_READ,ROLE_WRITE" />
        </user-service>
    </authentication-provider>
</authentication-manager>

服务层保护

这里的服务方法受到特定角色的保护

<beans:bean id="testService" class="com.stackoverflow.test" scope="request">
    <security:intercept-methods>
        <security:protect access="ROLE_WRITE" method="do*"/>
        <security:protect access="ROLE_READ" method="find*"/>
    </security:intercept-methods>
</beans:bean>

这个来源 (Spring Security Java Config for Siteminder) 看起来很有希望,但它总是被分配角色 RoleEmployee。

【问题讨论】:

  • 我建议阅读 Spring Security 文档中关于 Pre-Authentication 过滤器的章节。它直接谈到了 SiteMinder,我相信它提供了工作示例。有问题的章节可以在这里找到:docs.spring.io/spring-security/site/docs/3.0.x/reference/…
  • 是的,我的想法是修改 UserDetailsS​​ervice 以获取 SM_USER 并将值放入权限中。
  • UserDetailsService 是一个接口。只需制作一个并将其添加到您的配置中。我相信 SiteMinder 可以配置为包含用户角色作为传入标头的一部分。您的自定义 UserDetailsService 必须获取该标头的值(我想我记得它是“SM_ROLES”或类似的东西)和解析出角色。 Spring 论坛上的这篇帖子提供了一种解决方案:forum.spring.io/forum/spring-projects/security/…

标签: java spring spring-mvc spring-security siteminder


【解决方案1】:

SiteMinder 的 Spring Security 仅用于接收用户。但是,要接收角色,您需要创建扩展的身份验证过程。这将使用角色对用户进行身份验证。

root-security.xml

<beans:bean id="userDetailsService" class="test.sm.SiteMinderUserDetailsService"/>

<beans:bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
    <beans:property name="preAuthenticatedUserDetailsService">
        <beans:bean id="userDetailsServiceWrapper" class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
            <beans:property name="userDetailsService" ref="userDetailsService" />
        </beans:bean>
    </beans:property>
</beans:bean>

<beans:bean id="siteminderFilter" class="test.sm.SiteMinderFilter">
    <beans:property name="principalRequestHeader" value="SM_USER" />
    <beans:property name="rolesRequestHeader" value="SM_ROLE" />
    <beans:property name="rolesDelimiter" value="," />
    <beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>

<authentication-manager alias="authenticationManager">
    <authentication-provider ref="preauthAuthProvider" />
</authentication-manager>

SiteMinderUserDetailsS​​ervice

public class SiteMinderUserDetailsService extends PreAuthenticatedGrantedAuthoritiesUserDetailsService implements
        UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String arg0) throws UsernameNotFoundException {
        SiteMinderUserDetails userDetails = new SiteMinderUserDetails();
        userDetails.setUsername(arg0);      
        return userDetails;
    }

    @Override
    protected UserDetails createuserDetails(Authentication token, Collection<? extends GrantedAuthority> authorities) {
        return super.createuserDetails(token, authorities);
    }
}

SiteMinderUserDetails

public class SiteMinderUserDetails implements UserDetails {
    // implement all methods
}

SiteMinderFilter

public class SiteMinderFilter extends RequestHeaderAuthenticationFilter {

    private String rolesRequestHeader;
    private String rolesDelimiter;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException, NullPointerException {

        String roles = (String)  ((HttpServletRequest)request).getHeader(getRolesRequestHeader());
        String[] rolesArray = roles.split(rolesDelimiter);

        Collection<SimpleGrantedAuthority> auth = new ArrayList<SimpleGrantedAuthority>();
        for (String s : rolesArray) {               
            auth.add(new SimpleGrantedAuthority(s));
        }

        SiteMinderUserDetails userDetails = new SiteMinderUserDetails();
        userDetails.setUsername((String) super.getPreAuthenticatedPrincipal(((HttpServletRequest)request)));
        userDetails.setAuthorities(auth);

        AuthenticationImpl authentication = new AuthenticationImpl();
        authentication.setAuthenticated(true);
        authentication.setAuthorities(auth);
        authentication.setPrincipal(userDetails);
        authentication.setCredentials(super.getPreAuthenticatedCredentials(((HttpServletRequest)request)));
        SecurityContextHolder.getContext().setAuthentication(authentication);

        super.doFilter(request, response, chain);
    }

    public SiteMinderFilter() {
        super();        
    }

    @Override
    public void setPrincipalRequestHeader(String principalRequestHeader) {
        super.setPrincipalRequestHeader(principalRequestHeader);
    }

    public void setRolesRequestHeader(String rolesRequestHeader) {
        this.rolesRequestHeader = rolesRequestHeader;
    }

    public String getRolesRequestHeader() {
        return rolesRequestHeader;
    }


    public void setRolesDelimiter(String rolesDelimiter) {
        this.rolesDelimiter = rolesDelimiter;
    }

    public String getRolesDelimiter() {
        return rolesDelimiter;
    }
}

AuthenticationImpl

public class AuthenticationImpl implements Authentication {
    // implement all methods
}

【讨论】:

  • loadUserByUserName,我觉得有错误,因为SiteMinderUserDetails userDetails = new SiteMinderUserDetails(); userDetails.setUsername(arg0);不可能。 SiteMinderUserDetails 类中没有 setUsername 方法。我知道它实现了 UserDetails,但 UserDetails 没有任何设置器。请您详细说明并更新它。这是一个非常有用的答案,我只是希望它是完美的,这样它对很多像我这样的人都有用:) 谢谢!
  • 不久前我在网上倾倒了一堆代码。 learningthegoodstuff.com/2014/12/…
  • 我必须完全使用Java配置(无XML)实现授权,请您提供解决方案。
猜你喜欢
  • 1970-01-01
  • 2016-03-11
  • 1970-01-01
  • 2014-05-16
  • 1970-01-01
  • 2015-02-16
  • 2023-03-11
  • 2015-11-13
  • 2012-08-17
相关资源
最近更新 更多