我正在尝试使用Apache Shiro增强启用Spring的Web应用程序的安全性,从而将过滤链定义配置为弹簧配置文件。 我如何实现相当于
@Controller
@RequestMapping("/mywebapp")
// @RequiresAuthentication (is this possible ? wish i could do this !)
public class MyWebAppController {
@RequiresRoles(value={"Role1","Role2","Role3"},logical=Logical.OR)
@RequestMapping(value="/home", method = RequestMethod.GET)
public String home() { return .. }
我的spring-config文件包含: 假设我的dispatcherservlet映射到/ rest / *
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/rest/secure/windowslogin"/>
<property name="successUrl" value="/mywebapp/rest/menu"/>
<property name="unauthorizedUrl" value="/mywebapp/rest/unauthorized"/>
<property name="filters">
<util:map>
<entry key="anon">
<bean class="org.apache.shiro.web.filter.authc.AnonymousFilter"/>
</entry>
<entry key="authc">
<!-- why is this not invoked ? -->
<bean class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter">
</bean>
</entry>
<entry key="roles">
<bean class="org.apache.shiro.web.filter.authz.RolesAuthorizationFilter"/>
</entry>
</util:map>
</property>
<property name="filterChainDefinitions">
<value>
/rest/secure/** = anon
/rest/mywebapp/** = authc, roles[Role1,Role2,Role3]
</value>
</property>
</bean>
在上面的代码中,我需要使用提到的角色进行逻辑.OR映射到/rest/mywebapp/**
。这可以通过shiro注释实现,但它可以工作,而不是在每个方法中指定我宁愿在这里处理它(因为我不认为shiro支持类级别注释了吗?)。
这可能吗?
另外还要注意为什么不调用authc过滤器? (现在我们假设windows登录可以作为身份验证,仅使用shiro进行授权)
home page = meta refresh to /rest/secure/windowslogin/
if within intranet -> login ...
else /rest/secure/login ... login page.
是因为loginurl不同吗?我如何规避这个?请注意,虽然使用配置文件中指定的角色[..]部分调用了我的领域的getAuthorizationInfo但我假设应该检查请求是否为'authc'? (这可能意味着调用过滤器并检查SubjectUtils.getSubject()以进行身份验证)。我错过了流程或配置中的内容吗?
答案 0 :(得分:1)
这就是shiro-security.xml的样子。
<bean id="customFilter1" class="com.pkg.RolesAuthorizationFilter">
<property name="roles" value="ROLE1,ROLE3,ROLE5"></property>
</bean>
<bean id="customFilter2" class="com.pkg.RolesAuthorizationFilter">
<property name="roles" value="ROLE1,ROLE2,ROLE5,ROLE6"></property>
</bean>
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login" />
<property name="successUrl" value="/home" />
<property name="unauthorizedUrl" value="/unauthorized" />
<property name="filters">
<util:map>
<entry key="authc">
<bean class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter" />
</entry>
</util:map>
</property>
<property name="filterChainDefinitions">
<value>
/resources/** = anon
/login = anon
/logout = authc
/unauthorized = authc
/someurl/** = customFilter2
/** = customFilter1
</value>
</property>
</bean>
这是RolesAuthorizationFilter类
package com.pkg;
import java.util.Arrays;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.log4j.Logger;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
public class RolesAuthorizationFilter extends AuthorizationFilter {
protected Logger logger = Logger.getLogger(this.getClass()
.getCanonicalName());
private String[] roles;
@Override
protected boolean isAccessAllowed(ServletRequest request,
ServletResponse response, Object mappedValue) throws Exception {
logger.info("= Roles = " + Arrays.toString(roles));
Subject subject = getSubject(request, response);
boolean allowAccess = false;
for (String role : roles) {
if (subject.hasRole(role)) {
logger.info("Authenticated role " + role);
allowAccess = true;
break;
}
}
return allowAccess;
}
public void setRoles(String[] roles) {
this.roles = roles;
}
}