SpringMVC 整合shiro 实现url动态权限验证(二)

前言:上一篇文章讲述了如何使用shiro进行登录认证,其实主要的实现还是自定义Realm,继承AuthorizingRealm实现其中的

doGetAuthenticationInfo方法。上一篇文章链接:https://blog.csdn.net/xcc_2269861428/article/details/95107167

这篇文章主要实现url权限的认证,也就是roles的验证

如图:角色部分===》定义了2个角色,用户管理用户菜单、角色管理角色菜单

用户管理部分==》定义了2个用户

 为xcc这个用户分配了2个角色

url权限定义:

 

此时访问:http://127.0.0.1:8080/SpringShiroDemo/shiro_test/role/getRole/1?_=1562991213180

此时这个url没有被拦。

当我将【xcc】这个用的角色管理去掉

此时在访问:http://127.0.0.1:8080/SpringShiroDemo/shiro_test/role/getRole/1?_=1562991213180

显示权限不足。就是这么简单的功能,简单吧。

用户、角色的增删改查在这里就不描述了。主要说下shiro的关键点及代码展示。

一、ShiroFilterFactoryBean

首先从ShiroFilterFactoryBean说起:这个主要是用来配置登录、错误、url拦截的部分。

这里我重写了ShiroFilterFactoryBean,public class MyShiroFilterFactoryBean extends ShiroFilterFactoryBean {}

因为我们要从数据库中读取出我们配置的权限。只有这样才能称得上是动态修改权限!!!

package com.waysoft.common.shiro;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.shiro.config.Ini;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.util.CollectionUtils;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.annotation.Autowired;

import com.waysoft.modules.business.integrate.role.dao.RoleDao;

public class MyShiroFilterFactoryBean extends ShiroFilterFactoryBean {
	
	private static final String roles = "authc,roles[{0}]";

	@Autowired
	private RoleDao roleDao;
	
	@Override
	public void setFilterChainDefinitions(String definitions) {
		//System.out.println("权限认证");
		// /shiro_test/role/** =authc,roles[1]
		// /shiro_test/role/**=authc,roles[1]
		Ini ini = new Ini();
		ini.load(definitions);

		Ini.Section section = ini.getSection("urls");
		if (CollectionUtils.isEmpty(section)) {
			section = ini.getSection("");
		}
		Map<String,String> data = new HashMap<String,String>();
		// 从数据读取出数据
		List<Map<String,String>> menuRole = roleDao.getMenuRole();
		for(Map<String,String> map : menuRole){
			if(data.containsKey(map.get("url"))){
				String str = data.get(map.get("url"))+","+map.get("role_id");
				data.put(map.get("url"), str);
			}else{
				data.put(map.get("url"), map.get("role_id"));
			}
		}
		for(String url : data.keySet()){
			String str = MessageFormat.format(roles,data.get(url));
			section.put(url, str);
		}
		section.put("/**", "authc");
		super.setFilterChainDefinitionMap(section);
	}
	
	public void update(){
		synchronized (this) {
			try {
				AbstractShiroFilter shiroFilter = (AbstractShiroFilter)this.getObject();
				PathMatchingFilterChainResolver resolver = (PathMatchingFilterChainResolver)shiroFilter.getFilterChainResolver();
				DefaultFilterChainManager manager = (DefaultFilterChainManager)resolver.getFilterChainManager();
				manager.getFilterChains().clear();
				this.getFilterChainDefinitionMap().clear();
				Map<String, String> chains = this.getFilterChainDefinitionMap();
				Map<String,String> data = new HashMap<String,String>();
				// 从数据读取出数据
				List<Map<String,String>> menuRole = roleDao.getMenuRole();
				for(Map<String,String> map : menuRole){
					if(data.containsKey(map.get("url"))){
						String str = data.get(map.get("url"))+","+map.get("role_id");
						data.put(map.get("url"), str);
					}else{
						data.put(map.get("url"), map.get("role_id"));
					}
				}
				for(String url : data.keySet()){
					String str = MessageFormat.format(roles,data.get(url));
					chains.put(url, str);
				}
				chains.put("/**", "authc");
				
				if (!(CollectionUtils.isEmpty(chains))) {
					for (Map.Entry entry : chains.entrySet()) {
						String url = (String) entry.getKey();
						String chainDefinition = (String) entry.getValue();
						manager.createChain(url, chainDefinition);
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) {
		 System.out.println(MessageFormat.format(roles,2));
	}
}

此处重写了filterChainDefinitions方法、定义我们想要的数据。最后生成的样式就是 /shiro_test/role/** =authc,roles[1]

跟我们在ini 中配置的一样

之后自己写了一个update方法,它主要是用来更新权限的,shiro没有那么智能,所以只能我们自己手动去让它更新。

二、AuthorizationFilter

因为shiro默认是验证全部的权限,这里我并不想,有一个就通过,重写了AuthorizationFilter

package com.waysoft.common.shiro;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;

public class MyShiroFilter extends AuthorizationFilter {
	
    @Override
    protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception {
        Subject subject = getSubject(servletRequest, servletResponse);
        String[] roles = (String[]) o;
        if (roles == null || roles.length == 0) {
            return true;
        }
        for (String role : roles) {
            if (subject.hasRole(role)) {
                return true;
            }
        }
        return false;
    }
}

三、AuthorizingRealm

这个模块是最主要的了,登录会走doGetAuthenticationInfo方法,授权验证会走doGetAuthorizationInfo

package com.waysoft.common.shiro;

import java.util.Arrays;
import java.util.List;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

import com.waysoft.global.model.User;
import com.waysoft.modules.business.integrate.user.service.UserService;

public class UserRealm extends AuthorizingRealm {

	@Autowired
	private UserService userService;
	
	/**
	 * 授权验证
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
		System.out.println("=============");
		Subject subject = SecurityUtils.getSubject();
		Session session = subject.getSession();
		User user = (User)session.getAttribute("user");
		String[] ids = userService.getRoleIdByUserId(user.getId()+"");
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		if(ids.length > 0){
			List<String> asList = Arrays.asList(ids);
			info.addRoles(asList);
			return info;
		}
		return null; 
	}

	/**
	 * 登录验证
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
		// 账户名
		String username = (String) authenticationToken.getPrincipal();
		User user = userService.findUser(username);
		if(user != null){
			return new SimpleAuthenticationInfo(username,user.getPassword(),null,getName());
		}else{
			return null;
		}
	}

}

最最主要的是我们要在xml配置

<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor">

    </bean>
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
          depends-on="lifecycleBeanPostProcessor">
    </bean>  

否则有可能不走权限认证。。。

还有就是我们在为用户分配角色后,一定要手动更新权限

项目下载地址:https://download.csdn.net/download/xcc_2269861428/11343864

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值