Shiro - 自定义filterChainDefinitions和Realm

在Spring Context中定义shiroFilter(org.apache.shiro.spring.web.ShiroFilterFactoryBean)时需要为其filterChainDefinitions property赋值,这个属性是个chainName-to-chainDefinition map of chain definitions,用于为URL定义过滤策略。

比如:

/404.htm = anon
/main!main.html = anon
/**.html = perms[myPerm_1]

 


rest:比如/admins/user/**=rest[user],根据请求的方法,相当于/admins/user/**=perms[user:method] ,其中method为post,get,delete等。

port:比如/admins/user/**=port[8081],当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,queryString是你访问的url里的?后面的参数。

perms:比如/admins/user/**=perms[user:add:*],perms参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,比如/admins/user/**=perms["user:add:*,user:modify:*"],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。

roles:比如/admins/user/**=roles[admin],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,比如/admins/user/**=roles["admin,guest"],每个参数通过才算通过,相当于hasAllRoles()方法。

anon:比如/admins/**=anon 没有参数,表示可以匿名使用。
authc:比如/admins/user/**=authc表示需要认证才能使用,没有参数
authcBasic:比如/admins/user/**=authcBasic没有参数表示httpBasic认证
ssl:比如/admins/user/**=ssl没有参数,表示安全的url请求,协议为https
user:比如/admins/user/**=user没有参数表示必须存在用户,当登入操作时不做检查

 

一般情况下,我们可以将模块作为一个粒度,例如:

/blog!**.html = user

 

偶尔也会有将每一个URL作为一个授权单位进行控制,例如:

/blog!doAddNewArticle.html = authc,perms[addArticle]

 

但是URL的数量让人头疼,也许可以每开发一个功能的时候打开XML文件写入URL然后同步到SVN,或者我们也可以找一个人专门做这些事情,无论是添加、删除功能还是修改方法名都通知这个人去做...换位思考一下,我不希望我是这个人...

所以我要把这些URL放在数据库进行管理。我要把他们统统Query出来放到filterChainDefinitions里。
我需要装配一个Bean,实际上他是一个org.springframework.beans.factory.FactoryBean<Section>的实现。

<bean id="chainFilterBuff"   class="king.common.ChainFilterBuff">
    <property name="filterChainDefinitions">
    /404.htm = anon
    /main!main.html = anon
    </property>
</bean>

 

然后将其注入:

<bean id="shiroFilter1" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="securityManager" ref="securityManager" />
    <property name="loginUrl" value="/main!main.html" />
    <property name="successUrl" value="/main!main.html" />
    <property name="unauthorizedUrl" value="/unAuthorized.htm" />
    <property name="filterChainDefinitionMap" ref="chainFilterBuff" />
</bean>

 

Java代码中implements FactoryBean<Ini.Section>并实现需要Override的method,关键是getObject这个method:

private String filterChainDefinitions;
@Override
public Section getObject() throws Exception {
    Ini ini = new Ini();
    ini.load(filterChainDefinitions);   //先载入XML中定义好的chain
    Ini.Section section = ini.getSection(Ini.DEFAULT_SECTION_NAME);
    /*
     *  省略读取步骤
     *  继续加入数据库中的chain
     *  section.put("/**", "authc, roles[admin]");
     */
return section; }

 

等等,这些仅仅是定义了权限。
我们需要在用户访问这些URL的时候去验证一下用户是否具备当前URL权限。
所以我定义了(事实上我们必须定义一个Realm,ShiroFilterFactoryBean需要SecurityManager,而我们使用的SecurityManager的实现类DefaultWebSecurityManager则需要一个Realm!):

<bean id="shiroDataBaseRealm" class="king.security.KingMainRealm">

 

并且Override了接口定义的method:

public class KingMainRealm extends AuthorizingRealm {
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo( //授权
            PrincipalCollection principals) {
        UserBean _user = (UserBean) principals.fromRealm(getName()).iterator().next();
        SimpleAuthorizationInfo authInfo = new SimpleAuthorizationInfo();
        /*
         * 省略
         */
        return authInfo;
    }
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo( //认证
            AuthenticationToken token) throws AuthenticationException {
        UserBean user = new UserBean();
        UsernamePasswordToken userToken = (UsernamePasswordToken)token;
        user.setUserName(userToken.getUsername());
        user.setPassword(userToken.getPassword());
                                                                                                                            
        return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
    }
}

 

若已定义了需要请求的URL,用户登录时doGetAuthorizationInfo会被调用,剩下的就是为每一个用户管理这些权限了。
也许我们可以创建角色关联多个权限,用户关联多个角色,类似这样的设置不同的层次。
按自己喜欢的方式去做吧 :)

 

转载于:https://www.cnblogs.com/kavlez/p/4063885.html

### 自定义Realm在Spring中的集成与管理 在Spring框架中集成管理自定义Realm,主要是通过配置`SecurityManager`并将自定义Realm注入其中来实现。以下是具体实现方式的详细说明: #### 1. 创建自定义Realm类 首先需要创建一个继承`AuthorizingRealm`或`CachingAuthenticatingRealm`的类,并重写其认证授权逻辑。例如: ```java public class MyShiroRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // 实现授权逻辑 String username = (String) principals.getPrimaryPrincipal(); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); // 根据用户名查询权限信息 info.addRole("admin"); info.addStringPermission("user:read"); return info; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { // 实现认证逻辑 UsernamePasswordToken userToken = (UsernamePasswordToken) token; if ("admin".equals(userToken.getUsername())) { return new SimpleAuthenticationInfo( userToken.getUsername(), "123456".toCharArray(), // 密码 getName() ); } return null; } } ``` 此代码片段展示了如何自定义Realm类以处理用户认证授权[^1]。 #### 2. 配置Spring Bean 为了将自定义Realm集成到Spring中,需要在配置类中声明该Realm为一个Bean,并将其注入到`SecurityManager`中。以下是一个示例配置: ```java @Configuration public class ShiroConfig { @Bean public MyShiroRealm myShiroRealm() { return new MyShiroRealm(); // 返回自定义Realm实例 } @Bean public SecurityManager securityManager(MyShiroRealm myShiroRealm) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myShiroRealm); // 设置自定义Realm return securityManager; } } ``` 在此配置中,`myShiroRealm()`方法返回自定义Realm的实例,并通过依赖注入的方式传递给`securityManager()`方法[^2]。 #### 3. 配置过滤器链 为了确保请求能够正确地被拦截并进入Realm进行认证,需要配置Shiro的过滤器链。以下是一个典型的配置示例: ```xml <property name="filterChainDefinitions"> <value> /login.jsp = anon /login.action = authc /** = authc </value> </property> ``` 上述配置放过了`/login.jsp`页面的拦截,仅对其他请求进行认证,避免了死循环问题[^3]。 #### 4. 缓存与会话管理(可选) 如果需要支持缓存或会话管理,可以进一步扩展配置。例如: ```java @Bean public CacheManager cacheManager() { return new EhCacheManager(); // 使用EhCache作为缓存管理器 } @Bean public SessionManager sessionManager() { DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); sessionManager.setGlobalSessionTimeout(1800000); // 设置会话超时时间(毫秒) return sessionManager; } @Bean public SecurityManager securityManager(MyShiroRealm myShiroRealm, CacheManager cacheManager, SessionManager sessionManager) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myShiroRealm); securityManager.setCacheManager(cacheManager); securityManager.setSessionManager(sessionManager); return securityManager; } ``` 此部分代码展示了如何添加缓存管理会话管理功能[^2]。 ### 注意事项 - 确保自定义Realm类被正确声明为Spring Bean。 - 在`SecurityManager`中设置Realm时,推荐使用依赖注入而非直接实例化Realm对象。 - 正确配置过滤器链以避免不必要的拦截导致死循环。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值