【发布时间】:2016-02-27 12:07:34
【问题描述】:
我很难弄清楚如何使用 Spring Security 和 Spring MVC 在 servlet 中访问 CAS 发布的属性。传统上,在没有 Spring 的实现中,我会做这样的事情
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
// Gets the user ID from CAS
AttributePrincipal principal = (AttributePrincipal) request.getUserPrincipal();
final Map<String, Object> attributes = principal.getAttributes();
String userId = (String) attributes.get("userid");
// ...
}
使用 Spring MVC 创建 servlet,但没有 Spring Security 时,访问属性似乎基本没有区别:
@RequestMapping("/")
public String welcome(HttpServletRequest request)
{
// Get the user ID from CAS
AttributePrincipal principal = (AttributePrincipal) request.getUserPrincipal();;
final Map<String, Object> attributes = principal.getAttributes();
userId = (String) attributes.get("userid");
// ...
}
但是,在实现 Spring Security 之后,request.getUserPrincipal() 返回一个 CasAuthenticationToken 而不是 AttributePrincipal。据我所知,其中没有任何可检索的对象和数据包含任何 CAS 发布的属性。
环顾四周后,我确实注意到提到了GrantedAuthorityFromAssertionAttributesUserDetailsService 类,所以我将我的安全上下文.xml 从
<security:user-service id="userService">
<security:user name="user" password="user" authorities="ROLE_ADMIN,ROLE_USER" />
</security:user-service>
<bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<property name="authenticationUserDetailsService">
<bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<constructor-arg ref="userService" />
</bean>
</property>
<property name="serviceProperties" ref="serviceProperties" />
<property name="ticketValidator">
<bean class="org.jasig.cas.client.validation.Saml11TicketValidator">
<constructor-arg value="https://localhost:8443/cas" />
</bean>
</property>
<property name="key" value="casAuthProviderKey" />
</bean>
到
<bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<property name="authenticationUserDetailsService">
<bean class="org.springframework.security.cas.userdetails.GrantedAuthorityFromAssertionAttributesUserDetailsService">
<constructor-arg>
<list>
<value>userid</value>
</list>
</constructor-arg>
</bean>
</property>
<property name="serviceProperties" ref="serviceProperties" />
<property name="ticketValidator">
<bean class="org.jasig.cas.client.validation.Saml11TicketValidator">
<constructor-arg value="https://localhost:8443/cas" />
</bean>
</property>
<property name="key" value="casAuthProviderKey" />
</bean>
然后,通过一种更加迂回的方法,我可以通过执行以下操作来访问userid 属性:
@RequestMapping("/")
public String welcome(HttpServletRequest request)
{
CasAuthenticationToken principal = (CasAuthenticationToken) request.getUserPrincipal();
UserDetails userDetails = principal.getUserDetails();
Collection<SimpleGrantedAuthority> authorities = (Collection<SimpleGrantedAuthority>) userDetails.getAuthorities();
Iterator<SimpleGrantedAuthority> it = authorities.iterator();
String userid = it.next().getAuthority();
// ...
}
但是,除了比以前的实现稍微长一点之外,它似乎也不可能支持从 CAS 映射多个属性(例如,如果 CAS 还发布了firstName 和lastName 属性)。
是否有更好的方法来设置安全上下文 .xml 以允许更轻松地访问这些属性,尤其是当我想在 Web 应用程序中使用多个属性时?
【问题讨论】:
标签: spring-security cas