十、权限模型

本文介绍Shiro框架在权限管理中的应用,包括功能权限与内容权限的区别,基于URL的权限过滤实现,以及Shiro的架构组成如Subject、SecurityManager、Authenticator、Authorizer等。并提供SpringBoot与Shiro集成实例,展示如何配置ShiroFilterFactoryBean,实现用户认证和授权。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

任何系统都需要涉及权限的控制,通常权限控制的方法使用用户,角色,资源进行控制,用户具有角色,角色具有资源权限,相对于用户具有资源权限。
在这里插入图片描述

功能权限与内容权限

功能权限是某功能模块的权限,比如订单查询功能,哪些用户可以使用;内容权限是设计业务模板具体数据的权限,比如用户A的加班数据,用户B是不能查看与操作的,虽然用户B有加班功能的权限。功能权限可以很容易在系统框架一级实现,但内容权限控制通常在业务模块中实现。

功能实现通用实现方法

基于URL的权限过滤
实现思路是:将系统操作的每个url配置在权限表中,将权限对应到角色,将角色分配给用户,用户访问系统功能通过Filter进行过虑,过虑器获取到用户访问的url,只要访问的url是用户分配角色中的url则放行继续访问。
在这里插入图片描述

什么是shiro

Shiro是apache旗下一个开源框架,它将软件系统的安全认证相关的功能抽取出来,实现用户身份认证,权限授权、加密、会话管理等功能,组成了一个通用的安全认证框架。
Shiro架构
在这里插入图片描述

Subject

Subject即主体,外部应用与subject进行交互,subject记录了当前操作用户,将用户的概念理解为当前操作的主体,可能是一个通过浏览器请求的用户,也可能是一个运行的程序。Subject在shiro中是一个接口,接口中定义了很多认证授相关的方法,外部程序通过subject进行认证授,而subject是通过SecurityManager安全管理器进行认证授权

SecurityManager

SecurityManager即安全管理器,对全部的subject进行安全管理,它是shiro的核心,负责对所有的subject进行安全管理。通过SecurityManager可以完成subject的认证、授权等,实质上SecurityManager是通过Authenticator进行认证,通过Authorizer进行授权,通过SessionManager进行会话管理等。

SecurityManager是一个接口,继承了Authenticator, Authorizer, SessionManager这三个接口。

Authenticator

Authenticator即认证器,对用户身份进行认证,Authenticator是一个接口,shiro提供ModularRealmAuthenticator实现类,通过ModularRealmAuthenticator基本上可以满足大多数需求,也可以自定义认证器。

Authorizer

Authorizer即授权器,用户通过认证器认证通过,在访问功能时需要通过授权器判断用户是否有此功能的操作权限。

Realm

Realm即领域,相当于datasource数据源,securityManager进行安全认证需要通过Realm获取用户权限数据,比如:如果用户身份数据在数据库那么realm就需要从数据库获取用户身份信息。

SessionManager

sessionManager即会话管理,shiro框架定义了一套会话管理,它不依赖web容器的session,所以shiro可以使用在非web应用上,也可以将分布式应用的会话集中在一点管理,此特性可使它实现单点登录。

SessionDAO

SessionDAO即会话dao,是对session会话操作的一套接口,比如要将session存储到数据库,可以通过jdbc将会话存储到数据库。

CacheManager

CacheManager即缓存管理,将用户权限数据存储在缓存,这样可以提高性能。

Cryptography

Cryptography即密码管理,shiro提供了一套加密/解密的组件,方便开发。比如提供常用的散列、加/解密等功能。

Shiro应用

本例是SpringBoot与Shiro的集成例程

POM.xml配置

		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-core</artifactId>
			<version>1.4.0-RC2</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>1.4.0-RC2</version>
		</dependency>

配置类ShiroConfiguration

package com.hk.util;

import java.util.HashMap;
import java.util.Map;

import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerExceptionResolver;

@Configuration
public class ShiroConfiguration {

    //将自己的验证方式加入容器
    @Bean
    public HkShiroRealm myShiroRealm() {
    	HkShiroRealm myShiroRealm = new HkShiroRealm();
    	myShiroRealm.setCachingEnabled(false);
        return myShiroRealm;
    }

    //权限管理,配置主要是Realm的管理认证
    @Bean
    public org.apache.shiro.mgt.SecurityManager securityManager()
    {
    	DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        return securityManager;
    }

    //Filter工厂,设置对应的过滤条件和跳转条件
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(org.apache.shiro.mgt.SecurityManager securityManager)
    {
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		Map<String,String> map = new HashMap<String, String>();
		//登出
		map.put("/logout","logout");
		//对所有用户认证
		map.put("/*.action","authc");
		//过滤权限检查链接
		map.put("/static/**", "anon");
		map.put("/*.jsp", "anon");
		map.put("/*.txt", "anon");
		map.put("/wx/**", "anon");
		map.put("/wxapp/**", "anon");
		map.put("/downimg/**", "anon");
		map.put("/wxnotify/**", "anon");
		map.put("/weixinpay/**", "anon");
		//登录
		shiroFilterFactoryBean.setLoginUrl("/login");
		//首页
		shiroFilterFactoryBean.setSuccessUrl("/index");
		//错误页面,认证不通过跳转
		shiroFilterFactoryBean.setUnauthorizedUrl("/nopriv.jsp");
		shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
		return shiroFilterFactoryBean;
    }

    //加入注解的使用,不加入这个注解不生效
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(org.apache.shiro.mgt.SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
    
    @Bean
	public HandlerExceptionResolver solver(){
		HandlerExceptionResolver handlerExceptionResolver=new ShiroExceptionResolver();
		return handlerExceptionResolver;
	}
}

异常解析类ShiroExceptionResolver

package com.hk.util;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

public class ShiroExceptionResolver implements HandlerExceptionResolver{  
	  
    public ModelAndView resolveException(HttpServletRequest request,  
            HttpServletResponse response, Object handler, Exception ex)
    {
    	String url = request.getRequestURI();
        if(ex instanceof UnauthorizedException){  
            ModelAndView mv = new ModelAndView("nopriv");
            mv.addObject("url", url);
            return mv;
        }
        ex.printStackTrace();  
        ModelAndView mv = new ModelAndView("nopriv");
        mv.addObject("url", url);
        mv.addObject("exception", ex.toString().replaceAll("\n", "<br/>"));  
        return mv;
    }
}

自定义Realm
HkShiroRealm

package com.hk.util;

import java.util.List;

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.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import com.hk.bean.FunctionInfo;
import com.hk.bean.IRole;
import com.hk.bean.IUser;
import com.hk.bean.Permission;
import com.hk.service.IOrgModel;

//实现AuthorizingRealm接口用户用户认证
public class HkShiroRealm extends AuthorizingRealm{
	//用于用户查询
	@Autowired
	private IOrgModel orgmodel;
	
	//角色权限和对应权限添加
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection)
	{
		//获取登录用户名
		String name= (String) principalCollection.getPrimaryPrincipal();
		//查询用户名称
		IUser user = orgmodel.getUserByLoginId(name);
		SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
		//判断是否为超级管理员
		if(IConstants.I_SYSTEM_USERID.equals(user.getId()))
		{
			for (Permission perm:orgmodel.getAdminPerm()) {
				//添加权限
				simpleAuthorizationInfo.addStringPermission(perm.getPermission());
			}
		}
		else
		{
			//添加角色和权限
			List<IRole> roles = orgmodel.getRoleByUserId(user.getId());	
			for (IRole role:roles) {
				//添加角色
				simpleAuthorizationInfo.addRole(role.getName());
				for (Permission perm:orgmodel.getPermByRoleId(role.getId())) {
					//添加权限
					simpleAuthorizationInfo.addStringPermission(perm.getPermission());
				}
			}
		}
		return simpleAuthorizationInfo;
	}
	
	//用户认证
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) 
			throws AuthenticationException
	{
		//加这一步的目的是在Post请求的时候会先进认证,然后在到请求
		if (authenticationToken.getPrincipal() == null) {
			return null;
		}
		//获取用户信息
		String name = authenticationToken.getPrincipal().toString();
		IUser user = orgmodel.getUserByLoginId(name);
		if (user == null) {
			//这里返回后会报出对应异常
			return null;
		} else {
			//这里验证authenticationToken和simpleAuthenticationInfo的信息
			SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, user.getPassword().toString(),user.getName());
			return simpleAuthenticationInfo;
		}
	}
}

登录Controller

   //post登录
    @RequestMapping(value="/logindone",method=RequestMethod.POST)
    public String login(HttpServletRequest req,String loginId,String password){
        //添加用户认证信息
    	try
    	{
	        Subject subject = SecurityUtils.getSubject();
	        UsernamePasswordToken upToken = new UsernamePasswordToken(loginId,password);
	        //进行验证,这里可以捕获异常,然后返回对应信息
	        subject.login(upToken);
	        IUser user = orgmodel.getUserByLoginId(loginId);
	        HttpSession session = req.getSession();
	        session.setAttribute("user", user);
    	}
    	catch(UnknownAccountException uae)
    	{
    		req.setAttribute("showMsg", "账号错误");
    		return "login";
    	}
    	catch(IncorrectCredentialsException ice)
    	{
    		req.setAttribute("showMsg", "密码错误");
    		return "login";
    	}
        return "main";
    }

URL模块授权
在这里插入图片描述
这些权限需要通过角色分配给某用户
比如:
角色A具有权限url:wxact,权限url:wxact对应URL /wxact.action,具有此角色的用户可以访问Controller的act方法,用户B具有角色A,用户B登录系统后可以访问此URL /wxact.action

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值