springmvc整个shiro实现Perms的权限认证(细粒度)(三)

前言:上一篇文章讲述了如何使用角色url进行粗粒度验证。地址:https://blog.csdn.net/xcc_2269861428/article/details/95768417

这篇说下如何使用perms进行细粒度验证,已经我写代码过程中碰见的坑。

看下角色界面

我在数据库中分别为2个就是设置了perms权限

用户界面

图中可以看出,xcc是没有角色管理权限的,所以不能对角色进行增删改查。

当我用xcc这个用户点击角色部分按钮就会报错。

为xcc分配角色管理权限

再次点击角色部分的按钮,是可以的

 为什么要使用perms进行验证呢,因为他很细粒度化,他可以帮助我们精确到每个按钮,并且不需要太多的代码就可以实现。

看下controller部分的代码

package com.waysoft.modules.business.integrate.user.controller;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.waysoft.common.ResponseData;
import com.waysoft.global.model.Menu;
import com.waysoft.global.model.Role;
import com.waysoft.global.model.User;
import com.waysoft.modules.business.integrate.user.service.UserService;


@Controller
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
		  
    /**
	 * @Description 获取数据
	 * @param request
	 * @return ResponseData
	 */
    @RequestMapping(value="login", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    @ResponseBody
    public ResponseData save(HttpServletRequest request,User user){
    	ResponseData responseData=new ResponseData();
        try {
        	responseData = userService.login(user);
          }catch(Exception e){
          	responseData.setStatus(1);
  			responseData.setMsg("登录失败");
          }
      	return  responseData;
    }
    
    /**
     * 退出登录
     * @param request
     * @param user
     * @return
     */
    @RequestMapping(value="login_out", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
    @ResponseBody
    public ResponseData login_out(HttpServletRequest request,User user){
    	ResponseData responseData=new ResponseData();
        try {
        	Subject subject = SecurityUtils.getSubject();
        	subject.logout();
        	responseData.setStatus(0);
        	responseData.setMsg("退出成功");
          }catch(Exception e){
          	responseData.setStatus(1);
  			responseData.setMsg("退出失败");
          }
      	return  responseData;
    }
    
    /**
     * 添加用户
     * @param request
     * @param user
     * @return
     */
    @RequiresPermissions(value={"user:add"})
    @RequestMapping(value="insertUser", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    @ResponseBody
    public ResponseData insertUser(HttpServletRequest request,User user){
    	ResponseData responseData=new ResponseData();
        try {
        	userService.insertUser(user);
        	responseData.setStatus(0);
        	responseData.setMsg("添加成功");
          }catch(Exception e){
          	responseData.setStatus(1);
  			responseData.setMsg("添加失败");
          }
      	return  responseData;
    }
    
    /**
     * 回显用户
     * @param request
     * @param id
     * @return
     */
    @RequestMapping(value="getUser/{id}", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
    @RequiresPermissions(value={"user:get"}, logical = Logical.OR)
    @ResponseBody
    public ResponseData getUser(HttpServletRequest request,@PathVariable("id") String id){
    	ResponseData responseData=new ResponseData();
        try {
        	User user = userService.getUserById(id);
        	responseData.setStatus(0);
        	responseData.setData(user);
        	responseData.setMsg("获取成功");
          }catch(Exception e){
          	responseData.setStatus(1);
  			responseData.setMsg("获取失败");
          }
      	return  responseData;
    }
    
    /**
     * 修改用户
     * @param request
     * @param user
     * @return
     */
    @RequiresPermissions(value={"user:update"})
    @RequestMapping(value="updateUser", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    @ResponseBody
    public ResponseData updateUser(HttpServletRequest request,User user){
    	ResponseData responseData=new ResponseData();
        try {
        	userService.updateUser(user);
        	responseData.setStatus(0);
        	responseData.setMsg("修改成功");
          }catch(Exception e){
          	responseData.setStatus(1);
  			responseData.setMsg("修改失败");
          }
      	return  responseData;
    }
    
    /**
     * 获取菜单
     * @param request
     * @param id
     * @return
     */
    @RequiresPermissions(value={"user:getNode"})
    @RequestMapping(value="getRole/{id}", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
    @ResponseBody
    public ResponseData getRole(HttpServletRequest request,@PathVariable("id") String id){
    	ResponseData responseData=new ResponseData();
        try {
        	List<Menu> menu = userService.getRole(id);
        	responseData.setStatus(0);
        	responseData.setData(menu);
        	responseData.setMsg("获取成功");
          }catch(Exception e){
          	responseData.setStatus(1);
  			responseData.setMsg("获取失败");
          }
      	return  responseData;
    }
    
    /**
     * 插入菜单
     * @param request
     * @param id
     * @param urls
     * @return
     */
    @RequiresPermissions(value={"user:addNode"})
    @RequestMapping(value="insertNode", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    @ResponseBody
    public ResponseData insertNode(HttpServletRequest request,String id,String urls){
    	ResponseData responseData=new ResponseData();
        try {
        	userService.saveNode(id,urls);
        	responseData.setStatus(0);
        	responseData.setMsg("添加成功");
          }catch(Exception e){
          	responseData.setStatus(1);
  			responseData.setMsg("添加失败");
          }
      	return  responseData;
    }
    
    @RequestMapping(value="list", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
    @ResponseBody
    public ResponseData list(HttpServletRequest request){
    	ResponseData responseData=new ResponseData();
        try {
        	List<String> list = new ArrayList<>();
        	list.add("123");
        	list.add("456");
        	list.add("789");
        	//responseData = userService.login(user);
        	responseData.setStatus(0);
        	responseData.setMsg("获取数据成功");
        	responseData.setData(list);
          }catch(Exception e){
          	responseData.setStatus(1);
  			responseData.setMsg("获取数据失败");
          }
      	return  responseData;
    }
}
package com.waysoft.modules.business.integrate.role.controller;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.waysoft.common.ResponseData;
import com.waysoft.global.model.Menu;
import com.waysoft.global.model.Role;
import com.waysoft.modules.business.integrate.role.service.RoleService;


@Controller
@RequestMapping("/role")
public class RoleController {
    @Autowired
    private RoleService roleService;
		  
    /**
     * 添加角色
     * @param request
     * @param role
     * @return
     */
    @RequiresPermissions("role:add")
    @RequestMapping(value="insertRole", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    @ResponseBody
    public ResponseData insertRole(HttpServletRequest request,Role role){
    	ResponseData responseData=new ResponseData();
        try {
        	roleService.insertRole(role);
        	responseData.setStatus(0);
        	responseData.setMsg("添加成功");
          }catch(Exception e){
          	responseData.setStatus(1);
  			responseData.setMsg("添加失败");
          }
      	return  responseData;
    }
    
    /**
     * 回显角色
     * @param request
     * @param id
     * @return
     */
    @RequiresPermissions("role:get")
    @RequestMapping(value="getRole/{id}", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
    @ResponseBody
    public ResponseData getRole(HttpServletRequest request,@PathVariable("id") String id){
    	ResponseData responseData=new ResponseData();
        try {
        	Role role = roleService.getRole(id);
        	responseData.setStatus(0);
        	responseData.setData(role);
        	responseData.setMsg("获取成功");
          }catch(Exception e){
          	responseData.setStatus(1);
  			responseData.setMsg("获取失败");
          }
      	return  responseData;
    }
    
    /**
     * 修改角色
     * @param request
     * @param role
     * @return
     */
    @RequiresPermissions("role:update")
    @RequestMapping(value="updateRole", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    @ResponseBody
    public ResponseData updateRole(HttpServletRequest request,Role role){
    	ResponseData responseData=new ResponseData();
        try {
        	roleService.updateRole(role);
        	responseData.setStatus(0);
        	responseData.setMsg("修改成功");
          }catch(Exception e){
          	responseData.setStatus(1);
  			responseData.setMsg("修改失败");
          }
      	return  responseData;
    }
    
    /**
     * 获取菜单
     * @param request
     * @param id
     * @return
     */
    @RequiresPermissions("role:getNode")
    @RequestMapping(value="getMenu/{id}", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
    @ResponseBody
    public ResponseData getMenu(HttpServletRequest request,@PathVariable("id") String id){
    	ResponseData responseData=new ResponseData();
        try {
        	List<Menu> menu = roleService.getMenu(id);
        	responseData.setStatus(0);
        	responseData.setData(menu);
        	responseData.setMsg("获取成功");
          }catch(Exception e){
          	responseData.setStatus(1);
  			responseData.setMsg("获取失败");
          }
      	return  responseData;
    }
    
    /**
     * 插入菜单
     * @param request
     * @param id
     * @param urls
     * @return
     */
    @RequiresPermissions("role:addNode")
    @RequestMapping(value="insertNode", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    @ResponseBody
    public ResponseData insertNode(HttpServletRequest request,String id,String urls){
    	ResponseData responseData=new ResponseData();
        try {
        	roleService.saveNode(id,urls);
        	responseData.setStatus(0);
        	responseData.setMsg("添加成功");
          }catch(Exception e){
          	responseData.setStatus(1);
  			responseData.setMsg("添加失败");
          }
      	return  responseData;
    }
}

方法上我基本上都加入了权限验证   @RequiresPermissions("role:add")

由于我都是从数据库中读取的,所以我需要重写AuthorizingRealm

package com.waysoft.common.shiro;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

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.role.dao.RoleDao;
import com.waysoft.modules.business.integrate.user.service.UserService;

public class UserRealm extends AuthorizingRealm {

	@Autowired
	private UserService userService;
	
	@Autowired
	private RoleDao roleDao;
	
	/**
	 * 授权验证
	 */
	@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);
			for(String id : asList){
				String permsName = roleDao.getPermsByid(id);
				String perms [] = permsName.split(",");
				for(String prem :perms){
					info.addStringPermission(prem);
				}
			}
			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;
		}
	}

}

网上有很多种方法可以插入权限信息,但我用都不好使。比如:info.addStringPermissions(permissions);,没成功过,也在这卡了半天。最后我是使用addStringPermission实现的,原本我还有以为这样循环会覆盖原来的值,经测试,并没有。

之后就是重写PermissionsAuthorizationFilter

这个真是太坑了。差点被他搞死,看下源码

 

画红框的就是坑,它所验证的是一个,或者全部符合,是全等关系,而不是包含关系。

我要重写成包含关系

有一个符合就通过。

自定义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,perms[{0}]";
    // perms
	@Autowired
	private RoleDao roleDao;
	
	@Override
	public void setFilterChainDefinitions(String definitions) {
		//System.out.println("权限认证");
		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.getPerms_();
		for(Map<String,String> map : menuRole){
			if(data.containsKey(map.get("url"))){
				String str = data.get(map.get("url"))+","+map.get("perms_");
				data.put(map.get("url"), str);
			}else{
				data.put(map.get("url"), map.get("perms_"));
			}
		}
		for(String url : data.keySet()){
			String str = MessageFormat.format(roles,data.get(url));
			System.out.println(url+"="+str);
			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.getPerms_();
				for(Map<String,String> map : menuRole){
					if(data.containsKey(map.get("url"))){
						String str = data.get(map.get("url"))+","+map.get("perms_");
						data.put(map.get("url"), str);
					}else{
						data.put(map.get("url"), map.get("perms_"));
					}
				}
				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));
	}
}

还有就是要在xml中加入如下内容,否则注解不起作用

<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
    
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
          depends-on="lifecycleBeanPostProcessor">
          <property name="proxyTargetClass" value="true" />
    </bean>    
    
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>

资料下载地址:https://download.csdn.net/download/xcc_2269861428/11348378

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值