shiro利用mysql动态授权_续上篇---shiro从数据库获取动态权限-cjq

个人觉得,上篇中讲到的注解的方式来控制方法的访问权限并没有那么灵活,且需要在代码中硬编码,复用性不高,移植会很麻烦,故研究了下从数据库中动态加载权限

即shiro.xml中的ShiroFilterFactoryBean,之前是直接加载apache源码的bean:

现在做出以下自定义shiro的filter   该bean继承ShiroPermissionFactory,重写父类的setFilterChainDefinitions(java.lang.String definitions)方法

首先来看ShiroPermissionFactory源码,配置文件中的property 都是在为ShiroPermissionFactory属性赋值

源码部分:

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

// IntelliJ API Decompiler stub source generated from a class file

// Implementation of methods is not available

package org.apache.shiro.spring.web;

public class ShiroFilterFactoryBean implements org.springframework.beans.factory.FactoryBean, org.springframework.beans.factory.config.BeanPostProcessor {

private static final transient org.slf4j.Logger log;

private org.apache.shiro.mgt.SecurityManager securityManager;

private java.util.Map filters;

private java.util.Map filterChainDefinitionMap;

private java.lang.String loginUrl;

private java.lang.String successUrl;

private java.lang.String unauthorizedUrl;

private org.apache.shiro.web.servlet.AbstractShiroFilter instance;

public ShiroFilterFactoryBean() { /* compiled code */ }

public org.apache.shiro.mgt.SecurityManager getSecurityManager() { /* compiled code */ }

public void setSecurityManager(org.apache.shiro.mgt.SecurityManager securityManager) { /* compiled code */ }

public java.lang.String getLoginUrl() { /* compiled code */ }

public void setLoginUrl(java.lang.String loginUrl) { /* compiled code */ }

public java.lang.String getSuccessUrl() { /* compiled code */ }

public void setSuccessUrl(java.lang.String successUrl) { /* compiled code */ }

public java.lang.String getUnauthorizedUrl() { /* compiled code */ }

public void setUnauthorizedUrl(java.lang.String unauthorizedUrl) { /* compiled code */ }

public java.util.Map getFilters() { /* compiled code */ }

public void setFilters(java.util.Map filters) { /* compiled code */ }

public java.util.Map getFilterChainDefinitionMap() { /* compiled code */ }

public void setFilterChainDefinitionMap(java.util.Map filterChainDefinitionMap) { /* compiled code */ }

public void setFilterChainDefinitions(java.lang.String definitions) { /* compiled code */ }

public java.lang.Object getObject() throws java.lang.Exception { /* compiled code */ }

public java.lang.Class getObjectType() { /* compiled code */ }

public boolean isSingleton() { /* compiled code */ }

protected org.apache.shiro.web.filter.mgt.FilterChainManager createFilterChainManager() { /* compiled code */ }

protected org.apache.shiro.web.servlet.AbstractShiroFilter createInstance() throws java.lang.Exception { /* compiled code */ }

private void applyLoginUrlIfNecessary(javax.servlet.Filter filter) { /* compiled code */ }

private void applySuccessUrlIfNecessary(javax.servlet.Filter filter) { /* compiled code */ }

private void applyUnauthorizedUrlIfNecessary(javax.servlet.Filter filter) { /* compiled code */ }

private void applyGlobalPropertiesIfNecessary(javax.servlet.Filter filter) { /* compiled code */ }

public java.lang.Object postProcessBeforeInitialization(java.lang.Object bean, java.lang.String beanName) throws org.springframework.beans.BeansException { /* compiled code */ }

public java.lang.Object postProcessAfterInitialization(java.lang.Object bean, java.lang.String beanName) throws org.springframework.beans.BeansException { /* compiled code */ }

private static final class SpringShiroFilter extends org.apache.shiro.web.servlet.AbstractShiroFilter {

protected SpringShiroFilter(org.apache.shiro.web.mgt.WebSecurityManager webSecurityManager, org.apache.shiro.web.filter.mgt.FilterChainResolver resolver) { /* compiled code */ }

}

}------------------------------------------------------------------------------------------------------------------------------------------------

shiro.xml配置部分内容

//该部分的值被重写,部分数据从数据库加载

/login/**=anon

/api/** = authc

/main.do = authc

------------------------------------------------------------------------------------------------------------------------------------

自定义的shiro拦截器ShiroPermissionFactory

package cn.cjq.util.shiro;

import cn.cjq.entity.Menu;

import cn.cjq.service.user.UserService;

import org.apache.shiro.config.Ini;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;

import org.apache.shiro.util.CollectionUtils;

import org.apache.shiro.web.config.IniFilterChainResolverFactory;

import javax.annotation.Resource;

import java.util.List;

public class ShiroPermissionFactory extends ShiroFilterFactoryBean {

/**配置中的过滤链*/

public static String definitions;

/**权限service*/

@Resource

private UserService userServiceImpl;

/**

* 从数据库动态读取权限

*/

@Override

public void setFilterChainDefinitions(String definitions) {

ShiroPermissionFactory.definitions = definitions;

//数据库动态权限

List

try {

Menulist = userServiceImpl.ListMenu();

} catch (Exception e) {

e.printStackTrace();

}

//拼接所有请求(即url)所需要的权限(认证,权限ID),拼接时必须加入\n用来换行,否则无效。

for(Menu menu : Menulist){

//字符串拼接权限

definitions = definitions+menu.getUrl() + " = "+"authc,perms["+menu.getMenuid()+"]\n";

}

//从配置文件加载权限配置

Ini ini = new Ini();

ini.load(definitions);

Ini.Section section = ini.getSection(IniFilterChainResolverFactory.URLS);

if (CollectionUtils.isEmpty(section)) {

section = ini.getSection(Ini.DEFAULT_SECTION_NAME);

}

//加入权限集合

setFilterChainDefinitionMap(section);

}

/**

* 从数据库动态加载权限

*/

// public ShiroFilterFactoryBean getShiroFilterFactoryBean() {

// ShiroFilterFactoryBean shiroFilterFactoryBean=null;

// try {

// shiroFilterFactoryBean = new MyShiroFilterFactoryBean();

// //下列属性在配置文件中已配置

shiroFilterFactoryBean.setSecurityManager(getDefaultWebSecurityManager());

shiroFilterFactoryBean.setLoginUrl("/login");

shiroFilterFactoryBean.setSuccessUrl("/index.html");

shiroFilterFactoryBean.setUnauthorizedUrl("/403");

// loadShiroFilterChain(shiroFilterFactoryBean);

// } catch (Exception e) {

// e.printStackTrace();

// }

// return shiroFilterFactoryBean;

// }

//

// private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean) throws Exception {

// List

// Map filterChainDefinitionMap = new LinkedHashMap();

// for (Menu menu : Menulist) {

// filterChainDefinitionMap.put(menu.getUrl(),"authc,perms["+menu.getMenuid()+"]");

// }

// //配置文件中已配置

filterChainDefinitionMap.put("/login", "anon");

// shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

// }

}

-------------------------------------------------------------------------------------------------------------------------------

上述列出的是所有url所需的相对应权限ID,下面是自定义realm中的授权信息,列出当前用户所有的权限ID,通过比较是否存在权限问题。(也可通过角色去比较,暂不做说明)

/**

* 授权信息

*/

@Override

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

String username = (String)principals.getPrimaryPrincipal();

SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

// UserService userService = (UserService) SpringContextUtil.getBean("userServiceImpl");

try {

authorizationInfo.setRoles(userMapper.findUserRoles(username));

authorizationInfo.setStringPermissions(userMapper.findUserPermissions(username));

} catch (Exception e) {

e.printStackTrace();

}

return authorizationInfo;

}

------------------------------------------------------------------------------------------------------------------------------------------

根据当前用户获取所有权限ID:也可以不根据权限ID,使用别的也可,但必须统一,既然是使用了权限ID,所有查询结果返回权限ID即可

SELECT

m.menuId

FROM mif_user u

LEFT JOIN mif_role_user_ref ur ON u.uerId=ur.userId

LEFT JOIN mif_role r ON r.roleId=ur.roleId

LEFT JOIN mif_role_authority_ref ar ON ar.roleId=r.roleId

LEFT JOIN mif_authority a ON a.authorityId=ar.authorityId

LEFT JOIN mif_authotity_menu_ref mr ON mr.authorityId=ar.authorityId

LEFT JOIN mif_menu m ON m.menuId=mr.menuId

WHERE u.isdelete = 0 AND r.isdelete=0 AND a.isdelete=0 AND m.isdelete=0 AND u.userName = #{0}

--------------------------------------------------------------------------------------------------------------------------------------------

坑1:上述标红的\n未使用,无效果

坑2:在初始化静态拦截的时候存在初始值/person/**= authc,即/person下的所有方法只要通过认证即可请求。但是shiro权限中数据库的动态数据也包含了/person下的方法,是无效的,原因

是自定义的shiro的filter先加载配置文件中的数据,再加载数据库动态数据,存在/person/**= authc在前面时会让部分数据库/person下的url失效,注释掉/person/**= authc即可

//该部分的值被重写,部分数据从数据库加载

/login/**=anon

/api/** = authc

/main.do = authc

/person/**= authc

坑3:该bean只会在系统启动时加载一次,之后不会调用,所有存在任何权限上的变动时,需手动调用setFilterChainDefinitions()方法

PS:要记住在增删改权限数据库时记得调用setFilterChainDefinitions()方法重新加载

相关url:http://blog.csdn.net/u010351766/article/details/70432227

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值