我们有一个应用程序,其中具有代理权限的用户需要能够查看应用程序中的链接。
例如,我们可能会:
<s:intercept-url pattern="/resourceManager.htm" access=" ROLE_ADMIN_GROUP, ROLE_PROXY"/>
如果用户具有代理角色,而不是admin角色,我需要向他们提供一个页面,告诉他们需要处于代理模式才能看到此页面。此外,我需要检查他们代理的用户的权限,以验证他们是否具有正确的角色。
我们有多个页面,所以我想在过滤器中执行此逻辑,因此我们可以全面应用逻辑。
我在继续研究的过程中用伪代码嘲笑这个。
class Filter
{
protected void doFilterHttp()
{
//proxy summary is session based object
if(proxySummary.isProxyMode())
{
user = proxySummary.getProxiedUser()
//here load user's authorities
//will have to look at ldap authorities populator, but I should be able to work this part out
}
if(user.getGrantedAuthorities.contains("Role_Proxy"))
{
//Is there any way to tell possible valid roles for a url?
if(url.getPossibleRoles() intersect user.getGrantedAuthorities().size == 1 &&
intersection.contains(Role_Proxy))
{ redirectToProxyPage(); }
}
}
获取我尝试访问的网址的任何元数据的最佳方法是什么?
如果无法获取有关网址的所有允许角色的信息,那么我想我必须在页面上进行此操作。
升级到Spring Security 3会给我更多的灵活性吗?
答案 0 :(得分:0)
我最终创建了一个runAsManager实现,如果处于代理模式,它将作为代理用户运行。否则,如果用户只有链接的代理角色,则会重定向它们。 runAsManager仅在代理模式下修改了身份验证对象。
我已经包含了每个班级的片段,以免过长。
RunAsProxy代码段
public Authentication buildRunAs(Authentication authentication, Object object,
ConfigAttributeDefinition config) {
//probably need to do something to cache the proxied user's roles
if(proxySummary.isProxyMode())
{
SpringSecurityLdapTemplate template = new SpringSecurityLdapTemplate(contextSource);
String dn = proxySummary.getLoggedInUser();
String [] tmp = { "uid", "cn" };
DirContextOperations user = template.retrieveEntry(dn, tmp);
GrantedAuthority[] proxiedAuthorities = authoritiesPopulator.getGrantedAuthorities(user, user.getStringAttribute("cn").toString());
return new RunAsUserToken(this.key, authentication.getPrincipal(), authentication.getCredentials(),
proxiedAuthorities, authentication.getClass());
}
return null;
}
拦截代码 - &gt; extends AbstractSecurityInterceptor实现Filter,Ordered
public void invoke(FilterInvocation fi) throws IOException, ServletException {
//same code as from proxy security interceptor here ...
//config attributes are the roles assigned to a link
ConfigAttributeDefinition cad = ((DefaultFilterInvocationDefinitionSource)objectDefinitionSource).lookupAttributes(fi.getRequestUrl());
if(cad != null)
{
HashSet<String> configAttributes = new HashSet<String>();
for(Object ca: cad.getConfigAttributes())
{
configAttributes.add(((ConfigAttribute)ca).getAttribute());
}
SecurityContext sc = SecurityContextHolder.getContext();
HashSet<String> authorities = new HashSet<String>();
for(GrantedAuthority ga: sc.getAuthentication().getAuthorities())
{
authorities.add(ga.getAuthority());
}
//intersection and remaining available roles to determine
//if they just have the proxy role
authorities.retainAll(configAttributes);
if(authorities.size() == 1 && authorities.contains("ROLE_PROXY"))
{
//redirect to page telling them to proxy
((HttpServletResponse)fi.getResponse()).sendRedirect("jsp/doProxy.jsp");
}
//System.out.println(cad);
fi.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE);
//other boilderplate code
}
Spring Setup
<bean id="proxySecurityInterceptor" class="org.springframework.security.intercept.web.ProxySecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="_accessManager"/>
<property name="proxySummary" ref="proxySummary" />
<property name="runAsManager" ref="runAsProxy" />
<property name="objectDefinitionSource">
<s:filter-invocation-definition-source>
<s:intercept-url pattern="/groupManager.htm*" access="ROLE_GLOBAL_ADMIN, ROLE_ADMIN_GROUP, ROLE_PROXY"/>
</s:filter-invocation-definition-source>
</property>
<s:custom-filter after="FILTER_SECURITY_INTERCEPTOR" />
</bean>