Apache Shiro 框架的基本用法

本文介绍Shiro权限管理系统的核心概念及实现方法,包括基于Filter的URL级别权限控制、基于注解的方法级别权限控制以及如何集成Shiro进行登录和权限验证。

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

一、 权限控制两种主要方式
权限控制分为 粗粒度 URL 级别权限控制和细粒度方法级别权限控制
1.可以基于 Filter 实现
在数据库中存放 用户、权限、访问 URL 对应关系, 当前用户访问一个 URL 地址,查
询数据库判断用户当前具有权限,是否包含这个 URL,如果包含允许访问,如果不包含 权限不足 !!!
2.可以代理、自定义注解实现, 访问目标对象方法,在方法上添加权限注解信息,对目标对象创建代理对象,访问真实对象先访问代理对象,在代理对象查询数据库判断是否具有注解上描述需要权限,具有权限 允许访问,不具有权限,拦截访问,提示权限不足.
二.用户 角色 权限 ==> 建立 5 张数据表
三.实现权限控制, 可以自己写代码实现 (粗粒度权限控制 Filter、 细粒度权限控制 自
定义注解、代理、反射技术)
1、 自己写权限框架
2、 Spring Security (使用复杂, 依赖 Spring )
3、 Apache Shiro (更轻量, 使用更简单, 并不完全依赖 spring,可以独立使用 )

一.登录流程: 应用程序 — Subject — SecurityManager — Realm — 安全数据
ApplicationCode 用户编写代码
Subject 就是 shiro 管理的用户
SecurityManager 安全管理器,是 shiro 权限控制核心对象, 在编程时,只需要操作
Subject 方法, 底层调用 SecurityManager 方法,无需直接编程操作 SecurityManager
Realm 应用程序和安全数据之间连接器 ,应用程序 进行权限控制读取安全数据(数据
表、文件、网路 … ),通过 Realm 对象完成
二 . Shiro 进行权限控制
四种主要方式 :
1、 在程序中 通过 Subject 编程方式进行权限控制
2、 配置 Filter 实现 URL 级别粗粒度权限控制
3、 配置代理,基于注解实现细粒度权限控制
4、 在页面中使用 shiro 自定义标签实现 页面显示权限控制
三.访问流程:
1、 配置 web.xml(shiro) 2.applicationContext-shiro.xml(对应的shiro shiroFiterFactory) 3.(安全管理其 secritory)
4.配置一个生命周期
anon 未认证可以访问
authc 认证后可以访问
perms 需要特定权限才能访问
roles 需要特定角色才能访问
user 需要特定用户才能访问
port 需要特定端口才能访问
reset 根据指定 HTTP 请求访问才能访问

具体的代码实现
1.jar包引入

 <properties>
		<shiro.version>1.2.2</shiro.version>
	</properties>

	<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-all</artifactId>
			<version>${shiro.version}</version>
		</dependency>

2.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>

3.spring-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
		http://www.springframework.org/schema/data/jpa 
		http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
		
	
	
	<!-- 配置Shiro核心Filter  其要注意这个名字一定要与web.xml中配置的filter-name一致 --> 
	<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/xx.html* = perms[courier:list]
				/pages/xx.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>
	
	<!-- 配置Realm -->
	<bean id="xxxRealm" class="cn.xx.xx.xx.xxRealm">
		<!-- 缓存区的名字 就是 ehcache.xml 自定义 cache的name -->
		<property name="authorizationCacheName" value="xxx" />
	</bean>
	
	<bean id="lifecycleBeanPostProcessor"
		class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
 		
	<!-- 开启shiro注解模式 对于利用方法细粒化进行操作的时候需要配置proxyTrgetClass=true进行一cglib的形式扫描 -->
	<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>
	
</beans>

以上注意页面的跳转,准备好对应得页面信息,还要配置扫描信息

<context:component-scan base-package=“cn.xx”/>

4.java代码

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.authc.UsernamePasswordToken;
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.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;



// 自定义Realm ,实现安全数据 连接
// @Service("xxRealm")
public class xxRealm extends AuthorizingRealm {

	@Autowired
	private UserService userService;

	@Autowired
	private RoleService roleService;

	@Autowired
	private xxService xxService;

	@Override
	// 授权...
	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<xx> xx = xxService.findByUser(user);
		for (XX xx : x) {
			authorizationInfo.addStringPermission(xx.getKeyword());
		}

		return authorizationInfo;
	}

	@Override
	// 认证...
	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());
		}

	}

}

5.其在登录与退出中要进行数据的保存操作

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;
		}
	}

	@Action(value = "user_logout", results = { @Result(name = "success", type = "redirect", location = "login.html") })
	public String logout() {
		// 基于shiro完成退出
		Subject subject = SecurityUtils.getSubject();
		subject.logout();

		return SUCCESS;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值