shiro+spring的基本配置+用法

1,导入jar包

在这里插入图片描述
和spring整合中需要在spring的jar包基础上导入这一个jar包即可

shiro整合ssm所需jar包

在这里插入图片描述

web.xml配置(主要配置shiro的过滤器,其他的是spring配置)

<!-- spring配置文件 -->
	<context-param>
	    <param-name>contextConfigLocation</param-name>
	    <param-value>classpath:spring.xml</param-value>
	</context-param>
	<listener>
	    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<!-- SpringMVC的配置文件 -->
	<servlet>
	    <servlet-name>springDispatcherServlet</servlet-name>
	    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	    <init-param>
	        <param-name>contextConfigLocation</param-name>
	        <param-value>classpath:springmvc.xml</param-value>
	    </init-param>
	    <load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
	    <servlet-name>springDispatcherServlet</servlet-name>
	    <url-pattern>/</url-pattern>
	</servlet-mapping>
	<!-- 添加shiro过滤器,用来拦截shiro请求 -->
	<!-- -----------------主要配置--------------------------- -->
	<filter>
	    <filter-name>shiroFilter</filter-name>
	    <filter-class>
		    org.springframework.web.filter.DelegatingFilterProxy
	    </filter-class>
	    <init-param>
	        <param-name>targetFilterLifecycle</param-name>
	        <param-value>true</param-value>
	    </init-param>
	</filter>
	<filter-mapping>
	    <filter-name>shiroFilter</filter-name>
	    <url-pattern>/*</url-pattern>
	</filter-mapping>
<!-- -------------------------------------------- -->

这里整合需要把shiro相关的配置在spring.xml配置文件中配置

spring.xml配置


<context:component-scan base-package="com.org.shiro">
		<!-- 排除扫描注解 -->
		<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
	</context:component-scan>
	
	
	<!-- 1.配置 securityManager管理器-->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
	    <!-- 缓存管理器 -->
	    <property name="cacheManager" ref="cacheManager"/>
	    <!-- 配置session的管理方式 -->
	    <!-- <property name="sessionMode" value="native"/> -->
	    <!-- 单个realm配置 -->
	    <!-- <property name="realm" ref="shiroRealm"/> -->
	    
	    <!-- 多realm配置(需要权限操作的要写在securityManager) -->
	    <property name="realms">
			<list>		
				<ref bean="shiroRealm" />
				<!-- <bean class="com.org.shiro.realm.NewShiroRealm"></bean> -->
			</list>
		</property>
	</bean>
	
	<bean id="modularRealmAuthenticator" class="org.apache.shiro.authc.pam.ModularRealmAuthenticator">
		<!-- 设置多个Realm的策略 -->
		<property name="authenticationStrategy">
		    <bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"></bean>
		</property>
	</bean>
	
	<!-- 2.配置缓存管理器,可以设置缓存 -->
	<!-- 2.1 添加ehcache的jar包和配置文件 -->
	<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
	    <!-- <property name="cacheManager" ref="ehCacheManager"/> -->
	    <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/> 
	</bean>
	
	<!-- 3.配置实现了realm接口的bean -->
	<bean id="shiroRealm" class="com.org.shiro.realm.ShiroRealm">
		<property name="credentialsMatcher">
		    <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
			    <!-- 指定使用MD5加密方式加密前台密码 -->
			    <property name="hashAlgorithmName" value="MD5" />
			    <!-- 指定使用MD5加密的次数 -->
			    <property name="hashIterations" value="3" />
		    </bean>
	    </property>
	</bean>
	
	<!-- 4.配置lifecycleBeanPostProcessor,可以自动调用配置在spring中的shrio对象生命周期方法。 -->
	<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
	
	<!-- 5.启用IOC容器中的shiro注解,但必须在配置 lifecycleBeanPostProcessor 后才会生效。-->
	<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
	          depends-on="lifecycleBeanPostProcessor"/>
	<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
	    <property name="securityManager" ref="securityManager"/>
	</bean>
		
	<!-- 
    6.配置shiroFilter过滤器相关的属性。
    6.1 id必须 和web.xml中配置的filter-name一致。
	-->
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
	    <property name="securityManager" ref="securityManager"/>
	    <property name="unauthorizedUrl" value="/unauthorized"/>
	    <property name="loginUrl" value="/login"/>
	    <!-- 
	         	配置哪些页面需要被保护,以及访问该页面所需要的权限。
	        	anon: 表示可以匿名访问。
	        	authc:表示需要登录之后才可以访问。
	    -->
	    <property name="filterChainDefinitions">
	        <value>
	            /login = anon
	            /start.jsp = anon
	            /user = roleOrFilter["1,2,3"]<!-- 已url允许多种角色访问,需要继承AuthorizationFilter类,重写isAccessAllowed方法 -->
	            /admin = roles[3]
	            /logout = logout	
	            /** = authc
	        </value>
	       <!--
			url模式使用ant风格模式
			Ant路径通配符支持?、*、**,注意通配符匹配不包括目录分隔符"/”
			?:匹配一个字符,如/admin?将匹配/admin1,但是不匹配/admin或/admin/。
			*:匹配另个或多个字符串,如/admin*将匹配/admin、/admin123,但是不匹配/admin/1。
			**:匹配路径中的另个或多个路径,如/admin/**将匹配/admin/a或/admin/a/b。
			
			-->
	    </property>
	</bean>
	
	
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> 
	    <property name="url" value="jdbc:mysql://localhost:3306/springmvc" />
	    <property name="username" value="root" />
	    <property name="password" value="157953" />
	</bean>
	
	
	
	<!-- Spring扫描所有的mapper文件 -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- 设置连接池对象 -->
		<property name="dataSource" ref="dataSource" />
		<!-- Mappper所在的包路径 -->
		<property name="mapperLocations" value="classpath:com/org/shiro/beans/*.xml" />
		<!-- 指定mybatis的配置文件 -->
		<property name="configLocation" value="classpath:conf.xml"></property>
	</bean>
	
	
	<!-- Spring 扫描DAO包 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<!-- DAO包所在的包路径 -->
		<property name="basePackage" value="com.org.shiro.dao" />
		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
	</bean>

	<bean id="roleOrFilter" class="com.org.shiro.realm.MyRolesAuthorizationFilter"/> 
	

还有个springmvc的xml,和不需要改变什么在这就不指出了

java试例

这个是登录验证

@RequestMapping(value = "/login",method = RequestMethod.POST)
	public String login(User user) {
		//获取当前的Subject
		Subject currentUser = SecurityUtils.getSubject();
		System.out.println(user+"========");
		// 测试当前用户是否已经被认证,即是否已经登录。
		if (!currentUser.isAuthenticated()) {
			// 把用户名和密码封装为UsernamePasswordToken对象
			UsernamePasswordToken token 
				= new UsernamePasswordToken(user.getName(), user.getPass());
			// 记住密码
			token.setRememberMe(true);
			try {
			// 执行登录
				currentUser.login(token); //实际上调用Realm中的doGetAuthenticationInfo方法
				return "index";
			}catch (UnknownAccountException uae) {  //当前用户不存在
				System.err.println("当前用户不存在"+token.getPrincipal());
            } catch (IncorrectCredentialsException ice) { //账户存在,密码错误
            	System.err.println("账户存在,密码错误"+token.getPrincipal());
            } catch (LockedAccountException lae) {  //用户被锁定
            	System.err.println("用户被锁定"+token.getPrincipal());
            }catch (AuthenticationException e) { // 其他异常,是其他异常的父类
			    e.printStackTrace();
			   
			}
		}
		return "login";
	}

编写身份验证的realm类

//添加授权功能需要继承AuthorizingRealm,这类继承与AuthenticatingRealm
public class ShiroRealm extends AuthorizingRealm{

	@Autowired
	private UserService us;
	
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		
		//①、把AuthenticationToken转换为UsernamePasswordToken。
		UsernamePasswordToken upToken = (UsernamePasswordToken) token;
		//②、从UsernamePasswordToken中获取username
		String username = upToken.getUsername();
		//③、调用数据库的方法,从数据库中查询username对应的记录。
		User user = us.login(username);
		System.out.println(user);
		//④、若用户不存在,则可以跑出UnknownAccountException异常。
		if(user == null) {
			throw new UnknownAccountException("用户不存在.");
		}
		//⑤、根据用户信息的情况,决定是否需要抛出其它AuthenticationException异常。
		if(user.isLock()) {
			throw new LockedAccountException("用户被锁定");
		}
		//⑥、根据用户的情况,来构建AuthenticationInfo对象并返回。
		//AuthenticationInfo info = new SimpleAuthenticationInfo(user.getName(), user.getPass(), this.getName());
		
		//生成加密的盐值
		//ByteSource salt = ByteSource.Util.bytes("xxx");
		//这里的密码要是数据库中加密之后的密码。
		AuthenticationInfo info = new SimpleAuthenticationInfo(user.getName(), user.getPass(), null, getName());

		return info;
	}

	
	
	//授权调用的方法
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		
		//-1.获取登录的用户名
		String s = (String) principals.getPrimaryPrincipal();
		System.out.println(s);
		
		//-2.通过登录的用户名获取其权限信息,可能用到数据库
		User user = us.login(s);
		Set<String> set = new HashSet<>();
		set.add(user.getQualification().toString());
		
		//-3.构建SimpleAuthorizationInfo ,并将set集合放入SimpleAuthorizationInfo之中
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(set);
		
		//-返回 SimpleAuthorizationInfo对象
		return info;
	}
}

Shiro内置了很多默认的拦截器,比如身份验证、授权等相关的。默认拦截器可以参考DefaultFilter枚举中的属性。
在这里插入图片描述
身份验证相关的拦截器
在这里插入图片描述
授权相关的拦截器
在这里插入图片描述
关于授权规则

规则:资源标识符:操作:对象实例ID即对哪个资源的哪个实例可以进行什么操作.其默认支持通配符权限字符串, 
“ : ” 表示资源/操作/实例的分割。
“,” 表示操作的分割。
“ * ” 表示任意资源/操作/实例。
多层次管理:
例如:user:query、user:edit
冒号是一个特殊字符,它用来分隔权限字符串的下一部件:第一部分是权限被操作的领域,第二部分是被执行的操作。
多个值:每个部件能够保护多个值。因此,除了授予用户user:query和user:edit权限外,也可以简单地授予他们一个:user:query, edit
还可以用* 号代替所有的值,如:user:* ,也可以写:*:query,表示某个用户在所有的领域都有query 的权限
实例级访问控制:
这种情况通常会使用三个部件:域、操作、被付诸实施的实例。如:user:edit:manager
也可以使用通配符来定义,如:user:edit:*、user:*:*、user:*:manager
部分省略通配符:缺少的部件意味着用户可以访问所有与之匹配的值,比如:user:edit等价于user:edit:*、user等价于user:*:*
注意:通配符只能从字符串的结尾处省略部件,也就是说user:edit并不等价于user:*:edit

关于shiro标签

Shiro提供了JSTL标签用于在JSP页面进行权限控制,如根据用户登录显示相应的页面按钮。

<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>

guest标签;用户没有登录显示相应的信息,即游客访问信息。

<shiro:guest>
    欢迎游客访问,<a href="login">登录</a>
</shiro:guest>

user标签:用户已经认证/使用记住我登录后显示的相应信息。

<shiro:user>
    欢迎[<shiro:principal />]登录,<a href="logout">注销</a>
</shiro:user>

authenticated标签:用户已经身份验证通过,即Subject.login登录成功,不是记住我登录的。

<shiro:authenticated>
    用户[<shiro:principal />]已身份验证通过。
</shiro:authenticated>

notAuthenticated标签:用户未进行身份验证,即没有调用Subject.login进行登录,包括记住我自动登录的也属于未进行身份验证。

<shiro:notAuthenticated>
    用户未身份验证。
</shiro:notAuthenticated>

pincipal标签:用户用户身份信息,默认调用Subject.getPrincipal()获取,如果AuthenticationInfo使用对象(User)作为参数,可以通过property来指定用户名的属性。

<shiro:user>
欢迎[<shiro:principal property="username"/>]登录,
<a href="logout">注销</a>
</shiro:user>

hasRole标签:如果当前Subject有角色,将显示body内容。

<shiro:hasRole name="admin">
  用户[<shiro:principal property="username"/>]拥有角色admin
</shiro:hasRole>

hasAnyRoles标签:如果当前Subject有任意一个角色,将显示body内容。

<shiro:hasAnyRoles name="admin,user">
  用户[<shiro:principal property="username"/>]拥有admin,user角色
</shiro:hasAnyRoles>

lacksRole:如果当前用户没有角色,将显示body体内容。

<shiro:lacksRole name="admin">
  用户[<shiro:principal property="username"/>]没有admin角色。
</shiro:lacksRole>

hasPermission:如果当前Subject有权限,则显示body内容。

<shiro:hasPermission name="user:create">
  用户[<shiro:principal property="username"/>]有user:create权限。
</shiro:hasPermission>

lacksPermission标签:如果当前Subject有没有权限,将显示body内容。

<shiro:hasPermission name="user:create">
  用户[<shiro:principal property="username"/>]有user:create权限。
</shiro:hasPermission>
权限注解
@RequiresAuthentication:表示当前Subject已经通过login 进行了身份验证;即Subject. isAuthenticated() 返回true
@RequiresUser:表示当前Subject 已经身份验证或者通过记住我登录的。
@RequiresGuest:表示当前Subject没有身份验证或通过记住我登录过,即是游客身份。
@RequiresRoles(value={“admin”, “user”}, logical= Logical.AND):表示当前Subject 需要角色admin 和user
@RequiresPermissions(value={“user:a”, “user:b”}, logical= Logical.OR):表示当前Subject 需要权限user:a或user:b。
从数据库中初始化资源和权限

该配置要在springmvc中配置,然后自定义工厂类(若是从数据库或资源要去掉xml文件的配置 )

<!-- 通过bean工厂来创建filterChainDefinitionMap -->
<bean id="filterChainDefinitionMap" factory-bean="filterChainDefinitionMapFactory" 
	factory-method="builderFilterChainDefinition" />
<!-- 将factory添加到spring容器中 -->
<bean id="filterChainDefinitionMapFactory" 
	class="com.org.shiro.realm.FilterChainDefinitionMapFactory" />

自定义的工厂类

//创建一个工厂,用来创建一个LinkedHashMap集合。
public class FilterChainDefinitionMapFactory {

	public LinkedHashMap<String, String> builderFilterChainDefinition(){
		LinkedHashMap<String, String> map = new LinkedHashMap<>();
		//将xml中配置的信息,通过键值对的方式添加到map中,
		//实际开发中可以从数据库中读取配置信息。
		map.put("/login", "anon");
		map.put("/index.jsp", "anon");
		map.put("/logout", "logout");
		map.put("/admin", "roles[admin]");
		map.put("/user", "roles[user]");
		map.put("/**", "authc");
		return map;
	}
}
会话管理

shiro 的session和servlet的session功能一样
在这里插入图片描述

会话监听器

需要实现该接口
在这里插入图片描述

设置Cookie的过期时间

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值