Shiro Spring 与 @RequiresRoles logical.OR 等效的过滤器链定义

Posted

技术标签:

【中文标题】Shiro Spring 与 @RequiresRoles logical.OR 等效的过滤器链定义【英文标题】:Shiro Spring with filterchain definitions equivalent for @RequiresRoles logical.OR 【发布时间】:2012-07-01 04:30:09 【问题描述】:

我正在尝试使用 Apache Shiro 来增强启用 spring 的 web 应用程序的安全性,因此我将过滤器链定义配置到 spring 配置文件中。 我如何实现相当于

@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>

在上面的代码中,我需要使用提到的角色对/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.

是因为登录网址不同吗?我该如何规避这个?请注意,虽然使用配置文件中指定的角色 [ .. ] 部分调用了我的领域的 getAuthorizationInfo .. 但我假设应该检查请求是否为 'authc' ? (这可能意味着调用了过滤器并检查了 SubjectUtils.getSubject() 以进行身份​​验证)。我是否在流程或配置中遗漏了什么?

【问题讨论】:

【参考方案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;
       

【讨论】:

以上是关于Shiro Spring 与 @RequiresRoles logical.OR 等效的过滤器链定义的主要内容,如果未能解决你的问题,请参考以下文章

spring与shiro整合

Shiro学习(12)与Spring集成

Shiro与Spring整合

spring与shiro配置详解

【Shiro】一步步的看Shiro 【Shiro与Spring Security区别】

Shiro与Spring集成