Apache Shiro权限框架

简介

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。

主要功能

三个核心组件:Subject, SecurityManager 和 Realms.

Subject:即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。但考虑到大多数目的和用途,你可以把它认为是Shiro的“用户”概念。
  Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。
  SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
  Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。
  从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。
  Shiro内置了可以连接大量安全数据源(又名目录)的Realm,如LDAP、关系数据库(JDBC)、类似INI的文本配置资源以及属性文件等。如果缺省的Realm不能满足需求,你还可以插入代表自定义数据源的自己的Realm实现。

权限控制两种主要方式


1.  粗粒度 URL 级别权限控制  

可以基于 Filter 实现 在数据库中存放 用户、权限、访问 URL 对应关系, 当前用户访问一个 URL 地址,查 询数据库判断用户当前具有权限,是否包含这个 URL,如果包含允许访问,如果不包含 权 限不足 !!! 
 2.  细粒度方法级别权限控制

可以代理、自定义注解实现, 访问目标对象方法,在方法上添加权限注解信息,对目 标对象创建代理对象,访问真实对象先访问代理对象,在代理对象查询数据库判断是否具有 注解上描述需要权限,具有权限 允许访问,不具有权限,拦截访问,提示权限不足 

ApacheShiro 框架入门  

1.  Apache Shiro 执行过程分析 和 权限控制主要方式 

1.1.  Shiro 运行主要运行流程  

ApplicationCode 用户编写代码  

Subject 就是 shiro 管理的用户  

SecurityManager 安全管理器,是 shiro 权限控制核心对象, 在编程时,只需要操作 Subject 方法, 底层调用 SecurityManager 方法,无需直接编程操作 SecurityManager  

Realm 应用程序和安全数据之间连接器 ,应用程序 进行权限控制读取安全数据(数据 表、文件、网路 … ),通过 Realm 对象完成   


 登录流程: 应用程序 --- Subject --- SecurityManager --- Realm --- 安全数据

1.2. Shiro 进行权限控制 

四种主要方式 :

1、 在程序中 通过 Subject 编程方式进行权限控制  

2、 配置 Filter 实现 URL 级别粗粒度权限控制  

3、 配置代理,基于注解实现细粒度权限控制  

4、 在页面中使用 shiro 自定义标签实现 页面显示权限控制 

用户登录功能实现 

配置 shiro 的 Filter 实现 URL 级别权限控制 

1、 配置 web.xml 

<!-- shiro的Filter  -->
	<filter> 
		<!-- 去spring配置文件中寻找同名bean  -->
		<filter-name>shiroFilter</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>shiroFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

2、 配置 applicationContext-shiro.xml 

<!-- 配置Shiro核心Filter  --> 
	<bean id="shiroFilter" 
		class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<!-- 安全管理器 -->
		<property name="securityManager" ref="securityManager" />
		<!-- 未认证,跳转到哪个页面  -->
		<property name="loginUrl" value="/login.html" />
		<!-- 登录页面页面 -->
		<property name="successUrl" value="/index.html" />
		<!-- 认证后,没有权限跳转页面 -->
		<property name="unauthorizedUrl" value="/unauthorized.html" />
		<!-- shiro URL控制过滤器规则  -->
		<property name="filterChainDefinitions">
			<value>
				/login.html* = anon
				/user_login.action* = anon 
				/validatecode.jsp* = anon
				/css/** = anon
				/js/** = anon
				/images/** = anon
				/services/** = anon 
				/pages/base/courier.html* = perms[courier:list]
				/pages/base/area.html* = roles[base]
				/** = authc
			</value>
		</property>
	</bean>
	
	<!-- 安全管理器  -->
	<bean id="securityManager" 
		class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="realm" ref="bosRealm" />
		<property name="cacheManager" ref="shiroCacheManager" />
	</bean>
	

参考: 

 用户登录(认证)功能实现  

1、 填写表单

2、 编写 UserAction 提供 login 登录方法  

public String login() {
		// 用户名和密码 都保存在model中
		// 基于shiro实现登录
		Subject subject = SecurityUtils.getSubject();

		// 用户名和密码信息
		AuthenticationToken token = new UsernamePasswordToken(
				model.getUsername(), model.getPassword());
		try {
			subject.login(token);
			// 登录成功
			// 将用户信息 保存到 Session
			return SUCCESS;
		} catch (AuthenticationException e) {
			// 登录失败
			e.printStackTrace();
			return LOGIN;
		}
	}

3、 自定义 Realm 对象,实现认证方法   自定义 Realm 实现 Realm 接口 (实际开发中,只需要继承 AuthorizingRealm ) 

	// 认证...
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {
		System.out.println("shiro 认证管理... ");

		// 转换token
		UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;

		// 根据用户名 查询 用户信息
		User user = userService.findByUsername(usernamePasswordToken
				.getUsername());
		if (user == null) {
			// 用户名不存在
			// 参数一: 期望登录后,保存在Subject中信息
			// 参数二: 如果返回为null 说明用户不存在,报用户名
			// 参数三 :realm名称
			return null;
		} else {
			// 用户名存在
			// 当返回用户密码时,securityManager安全管理器,自动比较返回密码和用户输入密码是否一致
			// 如果密码一致 登录成功, 如果密码不一致 报密码错误异常
			return new SimpleAuthenticationInfo(user, user.getPassword(),
					getName());
		}
	}
}

用户授权功能实现 

参考

实现 Realm 的授权方法 

// 授权...
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pc) {
		System.out.println("shiro 授权管理...");
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		// 根据当前登录用户 查询对应角色和权限
		Subject subject = SecurityUtils.getSubject();
		User user = (User) subject.getPrincipal();
		// 调用业务层,查询角色
		List<Role> roles = roleService.findByUser(user);
		for (Role role : roles) {
			authorizationInfo.addRole(role.getKeyword());
		}
		// 调用业务层,查询权限
		List<Permission> permissions = permissionService.findByUser(user);
		for (Permission permission : permissions) {
			authorizationInfo.addStringPermission(permission.getKeyword());
		}
		return authorizationInfo;
	}

 Apache Shiro 实现方法级别细粒度权限控制 

细粒度(方法)权限控制原因: 自定义注解(加在方法上,在注解中描述需要权限信 息),对目标业务对象创建代理对象,在代理方法中使用反射技术读取注解信息,获取需要 权限,查询当前登录用户具有权限是否满足 

1、  配置 applicationContext-shiro.xml  激活注解  
 

<!-- 开启shiro注解模式  -->
 <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>

针对 CourierServiceImpl 对象进行代理  

 <property name="securityManager" ref="securityManager"/>

使用方法注解进行权限控制, 当权限不足时,代理对象抛出一个异常   org.apache.shiro.authz.UnauthorizedException: Subject does not have permission [courier_add]

Apache Shiro 实现页面元素显示控制 

Apache Shiro 权限控制(小结)

第一种:URL 级别粗粒度权限控制 配置 web.xml 的 shiroFilter 拦截 /*  在 spring 的 applicationContext*.xml 配置文件中配置同名 bean,配置 filterChainDefinitions 拦截控制规则  

xxx.html* = anon (未登录可以访问)  

xxx.html* =authc (必须登录才能访问 )  

xxx.html* = perms[权限] (需要特定权限才能访问)

 xxx.html* = roles[角色] (需要特定角色才能访问 ) 
 
第二种: 方法级别细粒度权限控制  在 spring 的 applicationContext*.xml 配置 spring aop 对 spring 管理 bean 对象开启 shiro 注解支持  

@RequiresPermissions(权限)  需要特定权限才能访问  

@RequiresRoles(角色)  需要特定角色才能访问  

@RequiresAuthentication 需要认证才能访问  
 
第三种:通过 shiro 自定义标签,实现页面元素显示控制  

<shiro:authenticated> 登录后才能访问  

<shiro:hasPermission name="abc"> 需要特定权限才能访问  

<shiro:hasRole name="abc"> 需要特定角色才能访问 
 

 

  • 5
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值