shiro介绍和使用

编程

1、shiro 包含的组件

shiro主要包括认证器(Authenticator),授权器(Authrizer),session会话管理(SessionManager),加密处理(Cryptography),记住我(remember me),对权限的缓存(CacheManager)

2、shiro 各组件介绍

Subject:主体,可以理解为 与应用交互的用户    subject 里包含用户的所有信息  如 用户信息,用户角色,用户权限,是否登录等等;
SecurityManager:安全管理器  shiro通过securityManager 管理着整个shiro各个模块。
Authenticator:认证器,负责认证用户是否是合法用户       Authenticator具体认证过程 是通过realm 来处理用户是否是合法用户;
Authrizer:授权器, 负责给用户授权   Authrizer 具体授权是通过realm 来获取用户所具有的权限;
Realm:可以有1个或多个Realm,也可以自定义realm   realm在shiro框架中很重要  负责处理用户的认证信息和授权信息;
SessionManager:负责session的管理;
SessionDAO:对session的curd操作;
CacheManager:可以对用户权限信息进行缓存  提供性能;
Cryptography:密码模块, 对密码进行加密加盐处理;

shiro 通过securityManager认证管理器来管理认证器,授权器,会话管理器,缓存,sessionDao,realm ,应用端(app)通过subject 和securityManager认证管理器交互,认证管理器负责代理到认证器或者授权器,认证器或者授权器最后通过realm获取用户的认证信息或者授权信息

二、shiro 依赖的pom文件

<dependency>

<groupId>org.apache.shiro</groupId>

<artifactId>shiro-core</artifactId>

<version>1.3.2</version>

</dependency>

三、通过ini文件方式 使用shiro

1、 用户认证Demo

  shiro1.ini 文件内容如下

#users 模拟真实用户

[users]

# 格式 用户名=密码

xiaoming=123

xiaohong=123456

    @Test

public void testAuthenticate(){

//1、加载ini文件 通过ini文件创建IniSecurityManagerFactory

IniSecurityManagerFactory managerFactory = new IniSecurityManagerFactory("classpath:shiro1.ini");

//2、获取安全管理器(SecurityManager)

SecurityManager instance = managerFactory.getInstance();

//3、把当前SecurityManager 绑定到当前环境

SecurityUtils.setSecurityManager(instance);

//4、获取subject 主体对象

Subject subject = SecurityUtils.getSubject();

//5、设置用户名和密码

UsernamePasswordToken token = new UsernamePasswordToken("xiaoming","123");

//6、登录

subject.login(token);

//7、查看用户是否登录成功 true成功 false 失败

System.out.println(subject.isAuthenticated());

}

2、用户授权Demo

shiro2.ini 文件内容如下

#users 模拟真实用户

[users]

# 格式 用户名=密码,对应的角色 如 xiaoming 密码 是123 是admin角色 对应就拥有 user:save,user:delete,user:update,user:find权限

xiaoming=123,admin

xiaohong=123456,manager

#roles 模拟 角色信息

[roles]

#格式 角色名=角色对应拥有的权限 如admin角色拥有user:save,user:delete,user:update,user:find 权限 manager角色拥有 user:find权限

admin=user:save,user:delete,user:update,user:find

manager=user:find

    @Test

public void testAuthrizer(){

//1、加载ini文件 通过ini文件创建IniSecurityManagerFactory

IniSecurityManagerFactory managerFactory = new IniSecurityManagerFactory("classpath:shiro2.ini");

//2、获取安全管理器(SecurityManager)

SecurityManager instance = managerFactory.getInstance();

//3、把当前SecurityManager 绑定到当前环境

SecurityUtils.setSecurityManager(instance);

//4、获取subject 主体对象

Subject subject = SecurityUtils.getSubject();

//5、设置用户名和密码

UsernamePasswordToken token = new UsernamePasswordToken("xiaohong","123456");

//6、登录

subject.login(token);

//7、查看用户拥有的角色和权限

System.out.println(subject.hasRole("manager"));

System.out.println(subject.isPermitted("user:update"));

}

3、自定义realm Demo

   shiro3.ini文件内容如下

[main]

#声明自定义的realm名字 = 自定义realm类全限定名

customerRealm=com.xiao.shiro.CustomerRealm

#注册realm到securityManager中

securityManager.realms=$customerRealm

自定义realm

public class CustomerRealm extends AuthorizingRealm {

//自定义realm的名称 因为shiro框架中可能存在多个realm 根据realm的名称 来判断用哪个realm做处理

@Override

public void setName(String name) {

super.setName("CustomerRealm");

}

//授权 当主体(subject)调用获取用户角色时 会调用doGetAuthorizationInfo这个方法

@Override

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

System.out.println("授权开始");

//可以从principalCollection 获取用户信息

String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal();

SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

info.addRoles(Arrays.asList("manager","admin"));

info.addStringPermission("user:update");

return info;

}

//认证 当主体调用(subject)调用用户登录时 会调用 doGetAuthenticationInfo 这个方法

@Override

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

System.out.println("认证开始");

//用户登录的时候 subject.login(token); 传进来的token类型 是 UsernamePasswordToken

//所以可以把authenticationToken 强转成UsernamePasswordToken

UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;

String username = token.getUsername();

String pwd = new String (token.getPassword());

//模拟从数据库中查出来的用户名密码 分别是 xiaoming 123

if ("xiaoming".equals(username) && "123".equals(pwd)) {

//认证通过 把用户信息存到AuthenticationInfo 对象里

//SimpleAuthenticationInfo 三个参数 如下

//1、Object principal 用户信息 可以是任何类型的对象

//2、Object credentials 密码

//3、String realmName 当前realm的名称

AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username,pwd,getName());

return authenticationInfo;

}

//认证不通过 抛出异常

throw new RuntimeException("登录失败");

}

}

    @Test

public void testCustomerRealm(){

//1、加载ini文件 通过ini文件创建IniSecurityManagerFactory

IniSecurityManagerFactory managerFactory = new IniSecurityManagerFactory("classpath:shiro3.ini");

//2、获取安全管理器(SecurityManager)

SecurityManager instance = managerFactory.getInstance();

//3、把当前SecurityManager 绑定到当前环境

SecurityUtils.setSecurityManager(instance);

//4、获取subject 主体对象

Subject subject = SecurityUtils.getSubject();

//5、设置用户名和密码

UsernamePasswordToken token = new UsernamePasswordToken("xiaoming","123");

//6、登录 subject登录时会调用realm里的doGetAuthenticationInfo方法

subject.login(token);

//7、查看用户拥有的角色和权限 当subject获取角色或者权限时 会调用realm里的doGetAuthorizationInfo方法

System.out.println(subject.hasRole("manager"));

System.out.println(subject.isPermitted("user:find"));

}

4、使用缓存 存用户角色信息和权限信息 Demo

使用ehcache作为缓存

shiro-ehcache.xml  配置信息

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">

<defaultCache

maxElementsInMemory="1000"

maxElementsOnDisk="10000000"

eternal="false"

overflowToDisk="false"

diskPersistent="false"

timeToIdleSeconds="120"

timeToLiveSeconds="120"

diskExpiryThreadIntervalSeconds="120"

memoryStoreEvictionPolicy="LRU">

</defaultCache>

</ehcache>

    @Test

public void testCacheManager(){

//1、加载ini文件 通过ini文件创建IniSecurityManagerFactory

IniSecurityManagerFactory managerFactory = new IniSecurityManagerFactory("classpath:shiro3.ini");

//2、获取安全管理器(SecurityManager) 如果启用CacheManager 需要CachingSecurityManager 对象

CachingSecurityManager instance = (CachingSecurityManager) managerFactory.getInstance();

//3、创建缓存管理对象 (这里使用ehcache做缓存所以使用EhCacheManager) 可以使用其他的缓存对象

EhCacheManager ehCacheManager = new EhCacheManager();

//4、读取ehcache配置文件

ehCacheManager.setCacheManagerConfigFile("classpath:shiro-ehcache.xml");

//5、把EhCacheManager对象 设置到CachingSecurityManager 安全管理器中

instance.setCacheManager(ehCacheManager);

//6、把当前SecurityManager 绑定到当前环境

SecurityUtils.setSecurityManager(instance);

//7、获取subject 主体对象

Subject subject = SecurityUtils.getSubject();

//8、设置用户名和密码

UsernamePasswordToken token = new UsernamePasswordToken("xiaoming","123");

//9、登录

subject.login(token);

//10、查看用户拥有的角色和权限 第一次获取权限信息的时候会调用realm中的doGetAuthorizationInfo 方法 第二次 直接从缓存中获取 不走realm

System.out.println(subject.hasRole("manager"));

System.out.println(subject.isPermitted("user:find"));

}

5、清除缓存的用户信息

    @Test

public void testCacheManager(){

//1、加载ini文件 通过ini文件创建IniSecurityManagerFactory

IniSecurityManagerFactory managerFactory = new IniSecurityManagerFactory("classpath:shiro3.ini");

//2、获取安全管理器(SecurityManager) 如果启用CacheManager 需要CachingSecurityManager 对象

CachingSecurityManager instance = (CachingSecurityManager) managerFactory.getInstance();

//3、创建缓存管理对象 (这里使用ehcache做缓存所以使用EhCacheManager) 可以使用其他的缓存对象

EhCacheManager ehCacheManager = new EhCacheManager();

//4、读取ehcache配置文件

ehCacheManager.setCacheManagerConfigFile("classpath:shiro-ehcache.xml");

//5、把EhCacheManager对象 设置到CachingSecurityManager 安全管理器中

instance.setCacheManager(ehCacheManager);

//6、把当前SecurityManager 绑定到当前环境

SecurityUtils.setSecurityManager(instance);

//7、获取subject 主体对象

Subject subject = SecurityUtils.getSubject();

//8、设置用户名和密码

UsernamePasswordToken token = new UsernamePasswordToken("xiaoming","123");

//9、登录

subject.login(token);

//10、查看用户拥有的角色和权限 第一次获取权限信息的时候会调用realm中的doGetAuthorizationInfo 方法 第二次 直接从缓存中获取 不走realm

System.out.println(subject.hasRole("manager"));

System.out.println(subject.isPermitted("user:find"));

//获取ehcache 用户缓存信息

Cache<Object, Object> cache = ehCacheManager.getCache("CustomerRealm.authorizationCache");

//清除 xiaoming用户对应的缓存信息

cache.remove(new SimplePrincipalCollection("xiaoming", "CustomerRealm"));

//清除缓存后 获取用户角色和权限信息 重新从realm中获取

System.out.println(subject.hasRole("manager"));

System.out.println(subject.isPermitted("user:find"));

}

三、使用springboot  集成 shiro  

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>com.xiao.shiro</groupId>

<artifactId>shirodemo</artifactId>

<version>1.0-SNAPSHOT</version>

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>2.2.1.RELEASE</version>

</parent>

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

<dependency>

<groupId>org.mybatis.spring.boot</groupId>

<artifactId>mybatis-spring-boot-starter</artifactId>

<version>1.3.1</version>

</dependency>

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<version>8.0.13</version>

</dependency>

<dependency>

<groupId>tk.mybatis</groupId>

<artifactId>mapper-spring-boot-starter</artifactId>

<version>2.0.2</version>

</dependency>

<!--shiro核心-->

<dependency>

<groupId>org.apache.shiro</groupId>

<artifactId>shiro-core</artifactId>

<version>1.3.2</version>

</dependency>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>4.12</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>commons-logging</groupId>

<artifactId>commons-logging</artifactId>

<version>1.1.3</version>

</dependency>

<!-- ehcache -->

<dependency>

<groupId>net.sf.ehcache</groupId>

<artifactId>ehcache-core</artifactId>

<version>2.6.11</version>

</dependency>

<dependency>

<groupId>org.apache.shiro</groupId>

<artifactId>shiro-all</artifactId>

<version>1.3.2</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>com.alibaba</groupId>

<artifactId>fastjson</artifactId>

<version>1.2.44</version>

</dependency>

<!--spring和shiro整合 -->

<dependency>

<groupId>org.apache.shiro</groupId>

<artifactId>shiro-spring</artifactId>

<version>1.3.2</version>

</dependency>

<!--shiro与redis整合-->

<dependency>

<groupId>org.crazycake</groupId>

<artifactId>shiro-redis</artifactId>

<version>3.0.0</version>

</dependency>

<!--thymeleaf -->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-thymeleaf</artifactId>

</dependency>

</dependencies>

</project>

2、自定义realm

public class CustomerRealm extends AuthorizingRealm {

@Autowired

private UserInfoService userInfoService;

//自定义realm的名称 因为shiro框架中可能存在多个realm 根据realm的名称 来判断用哪个realm做处理

@Override

public void setName(String name) {

super.setName("CustomerRealm");

}

//授权 当主体(subject)调用获取用户角色时 会调用doGetAuthorizationInfo这个方法

@Override

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

System.out.println("授权开始");

//可以从principalCollection 获取用户信息

UserInfo userInfo = (UserInfo) principalCollection.getPrimaryPrincipal();

SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

UserDto userExtInfo = userInfoService.findUserExtInfo(userInfo.getId());

info.addRoles(userExtInfo.getRoles());

info.addStringPermissions(userExtInfo.getPermissions());

return info;

}

//认证 当主体调用(subject)调用用户登录时 会调用 doGetAuthenticationInfo 这个方法

@Override

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

System.out.println("认证开始");

//用户登录的时候 subject.login(token); 传进来的token类型 是 UsernamePasswordToken

//所以可以把authenticationToken 强转成UsernamePasswordToken

UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;

String username = token.getUsername();

String pwd = new String (token.getPassword());

UserInfo user = userInfoService.findUserByUserNameAndPwd(username, pwd);

//模拟从数据库中查出来的用户名密码 分别是 xiaoming 123

if (user != null) {

//认证通过 把用户信息存到AuthenticationInfo 对象里

//SimpleAuthenticationInfo 三个参数 如下

//1、Object principal 用户信息 可以是任何类型的对象

//2、Object credentials 密码

//3、String realmName 当前realm的名称

AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, pwd, getName());

return authenticationInfo;

}

//认证不通过 抛出异常

throw new RuntimeException("登录失败");

}

}

3、shiro 配置类

@Configuration

public class ShiroConfig {

//把自定义realm 交给spring容器管理

@Bean

public CustomerRealm getCustomerRealm(){

return new CustomerRealm();

}

@Bean

public SecurityManager getSecurityManager(CustomerRealm realm){

//创建安全管理器 并把realm交给管理器管理

DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(realm);

return securityManager;

}

//配置 shiro过滤条件和跳转页面

@Bean

public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){

ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();

//设置安全管理器

bean.setSecurityManager(securityManager);

//登录页面

bean.setLoginUrl("/tologin");

//授权失败跳转页面

bean.setUnauthorizedUrl("/toUnauthorized");

//必须用LinkedHashMap 要保证过滤的顺序

Map<String, String> map = new LinkedHashMap<>();

//anon 匿名访问 也就是说不用登录和授权就能访问

//authc 需要认证登录才能访问

//logout 注销 退出登录 跳转到 bean.setLoginUrl()方法设置的页面

//perms[xx] 有xx的权限才能访问

//roles[xx] 有xx的角色才能访问

map.put("/user/index", "anon");

//表示有select-user的权限才可以访问

map.put("/user/select", "perms[select-user]");

//表示系统管理员的角色才能访问

map.put("/user/delete", "roles[系统管理员]");

//只有认证登录才能访问

map.put("/user/**", "authc");

//设置请求的过滤链 过滤链是有顺序的 需要认证的一般放在匿名访问的后面

bean.setFilterChainDefinitionMap(map);

return bean;

}

}

4、测试controller

@Controller

public class TestController {

@RequestMapping("/login")

public String login(UserInfo userInfo) {

try {

UsernamePasswordToken upt = new UsernamePasswordToken(userInfo.getUsername(), userInfo.getPassword());

SecurityUtils.getSubject().login(upt);

return "登录成功";

} catch (Exception e) {

e.printStackTrace();

return "登录失败";

}

}

@RequestMapping("/user/index")

@ResponseBody

public String index(){

return "访问index成功";

}

@RequestMapping("/user/select")

@ResponseBody

public String select(){

return "访问select成功";

}

@RequestMapping("/user/delete")

@ResponseBody

public String delete(){

return "访问delete成功";

}

@RequestMapping("/user/login")

@ResponseBody

public String login(){

return "访问login成功";

}

//跳登录页

@RequestMapping("/tologin")

public String tologin(){

return "login";

}

//跳未授权页面

@RequestMapping("/toUnauthorized")

public String toUnauthorized(){

return "unauthorized";

}

}

5、shiro注解的方式  做权限控制

(1)、pom文件添加依赖  参考上面依赖即可

(2)、shiro 配置类 增加 DefaultAdvisorAutoProxyCreator,AuthorizationAttributeSourceAdvisor  这两个对象的配置

@Configuration

public class ShiroConfig {

//开启shiro注解的方式 要配置 ,DefaultAdvisorAutoProxyCreator,AuthorizationAttributeSourceAdvisor 这两个对象

@Bean

public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {

DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();

//开启对springaop的代理

autoProxyCreator.setProxyTargetClass(true);

return autoProxyCreator;

}

@Bean

public CustomerRealm getCustomerRealm(){

return new CustomerRealm();

}

@Bean

public SecurityManager getSecurityManager(CustomerRealm realm){

//创建安全管理器 并把realm交给管理器管理

DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(realm);

return securityManager;

}

//配置 启动shiro注解

@Bean

public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(SecurityManager securityManager) {

AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();

advisor.setSecurityManager(securityManager);

return advisor;

}

//配置 shiro过滤条件和跳转页面

@Bean

public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){

ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();

//设置安全管理器

bean.setSecurityManager(securityManager);

//登录页面

bean.setLoginUrl("/tologin");

//授权失败跳转页面

bean.setUnauthorizedUrl("/toUnauthorized");

//必须用LinkedHashMap 要保证过滤的顺序

Map<String, String> map = new LinkedHashMap<>();

//anon 匿名访问 也就是说不用登录和授权就能访问

//authc 需要认证登录才能访问

//logout 注销 退出登录 跳转到 bean.setLoginUrl()方法设置的页面

//perms[xx] 有xx的权限才能访问

//roles[xx] 有xx的角色才能访问

map.put("/user/index", "anon");

map.put("/login", "anon");

//表示有select-user的权限才可以访问

map.put("/user/select", "perms[select-user]");

//表示系统管理员的角色才能访问

map.put("/user/delete", "roles[系统管理员]");

//只有认证登录才能访问

map.put("/**", "authc");

//设置请求的过滤链 过滤链是有顺序的 需要认证的一般放在匿名访问的后面

bean.setFilterChainDefinitionMap(map);

return bean;

}

(3)、测试controller

@Controller

public class TestController {

//跳登录页

@RequestMapping("/tologin")

public String tologin(){

return "login";

}

//跳未授权页面

@RequestMapping("/toUnauthorized")

public String toUnauthorized(){

return "unauthorized";

}

//同时有user-add和user-delete 权限才能访问

@RequiresPermissions(value = {"user-add","user-delete"})

@RequestMapping("/testPermission")

@ResponseBody

public String testPermission(){

return "测试 Permission 成功";

}

//有管理员角色 才能访问

@RequiresRoles(value = "管理员")

@RequestMapping("/testRoles")

@ResponseBody

public String tesRoles(){

return "测试 role 成功";

}

}

shiro基于过滤器链(如 map.put("/**", "authc"))的方式和基于注解的方式(如@RequiresRoles) 再没有权限访问的时候处理方式不同

过滤链的方式 如果没有权限会跳转到 setUnauthorizedUrl("/toUnauthorized")  设置的地址

注解的方式 如果没有权限会抛AuthorizationException异常  可以自定义一个全局异常  来处理注解方式没有权限访问    代码如下

@ControllerAdvice

public class CustomerExceptionHandler {

//捕获AuthorizationException类型的异常

@ExceptionHandler(value = AuthorizationException.class)

@ResponseBody

public String error(HttpServletRequest request, HttpServletResponse response,AuthorizationException e) {

return "未授权";

}

}

四、shiro 密码加密

 public static void main(String[] args) {

//三个参数如下

//1、Object source 原始密码

//2、Object salt 盐值

//3、int hashIterations 加盐几次

Md5Hash pwd = new Md5Hash("12345", "salt", 2);

System.out.println(pwd.toString());

}

五、springboot 整合shiro的 会话session管理   把会话放到redis中存储

shiro 默认提供了三个sessionManager 默认实现

(1). DefaultSessionManager:用于JavaSE环境
(2). ServletContainerSessionManager:用于Web环境,web环境默认使用这个实现类   session信息存在httpSession里
(3). DefaultWebSessionManager:用于web环境,自己维护会话 可以把session信息存在指定的地方 如mysql,redis

1、引入shiro-redis 依赖

<dependency>

<groupId>org.crazycake</groupId>

<artifactId>shiro-redis</artifactId>

<version>3.0.0</version>

</dependency>

2、再application.yml引入redis 配置

 spring:

redis:

host: 127.0.0.1

port: 6379

3、自定义shiro会话管理器

public class CustomerSessionManager extends DefaultWebSessionManager {

/**

* 头信息中具有sessionid

* 请求头:Authorization: sessionid

*

* 指定sessionId的获取方式

*/

@Override

protected Serializable getSessionId(ServletRequest request, ServletResponse response) {

//获取请求头Authorization中的数据

String id = WebUtils.toHttp(request).getHeader("Authorization");

if(StringUtils.isEmpty(id)) {

//如果没有携带,生成新的sessionId

return super.getSessionId(request,response);

}else{

//指定sessionId的来源 指定从请求头里获取sessionId 不指定默认从cookie中获取

request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, "header");

//sessionId

request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);

request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);

return id;

}

}

}

4、配置shiro 会话管理 放到redis中存储

package com.xiao.shiro.config;

import com.xiao.shiro.realm.CustomerRealm;

import com.xiao.shiro.session.CustomerSessionManager;

import org.apache.shiro.mgt.SecurityManager;

import org.apache.shiro.spring.LifecycleBeanPostProcessor;

import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;

import org.apache.shiro.web.mgt.DefaultWebSecurityManager;

import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;

import org.crazycake.shiro.RedisCacheManager;

import org.crazycake.shiro.RedisManager;

import org.crazycake.shiro.RedisSessionDAO;

import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import java.util.HashMap;

import java.util.LinkedHashMap;

import java.util.Map;

@Configuration

public class ShiroConfig {

@Bean

public CustomerRealm getCustomerRealm(){

return new CustomerRealm();

}

@Bean

public SecurityManager getSecurityManager(CustomerRealm realm){

//创建安全管理器 并把realm交给管理器管理

DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(realm);

//将自定义的会话管理器注册到安全管理器中

securityManager.setSessionManager(sessionManager());

//将自定义的redis缓存管理器注册到安全管理器中

securityManager.setCacheManager(cacheManager());

return securityManager;

}

//配置 启动shiro注解

@Bean

public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(SecurityManager securityManager) {

AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();

advisor.setSecurityManager(securityManager);

return advisor;

}

//配置 shiro过滤条件和跳转页面

@Bean

public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){

ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();

//设置安全管理器

bean.setSecurityManager(securityManager);

//登录页面

bean.setLoginUrl("/tologin");

//授权失败跳转页面

bean.setUnauthorizedUrl("/toUnauthorized");

//必须用LinkedHashMap 要保证过滤的顺序

Map<String, String> map = new LinkedHashMap<>();

//anon 匿名访问 也就是说不用登录和授权就能访问

//authc 需要认证登录才能访问

//logout 注销 退出登录 跳转到 bean.setLoginUrl()方法设置的页面

//perms[xx] 有xx的权限才能访问

//roles[xx] 有xx的角色才能访问

map.put("/user/index", "anon");

map.put("/login", "anon");

//表示有select-user的权限才可以访问

map.put("/user/select", "perms[select-user]");

//表示系统管理员的角色才能访问

map.put("/user/delete", "roles[系统管理员]");

//只有认证登录才能访问

map.put("/**", "authc");

//设置请求的过滤链 过滤链是有顺序的 需要认证的一般放在匿名访问的后面

bean.setFilterChainDefinitionMap(map);

return bean;

}

//开启shiro注解的方式 要配置 ,DefaultAdvisorAutoProxyCreator,AuthorizationAttributeSourceAdvisor 这两个对象

@Bean

public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {

DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();

//开启对springaop的代理

autoProxyCreator.setProxyTargetClass(true);

return autoProxyCreator;

}

@Value("${spring.redis.host}")

private String host;

@Value("${spring.redis.port}")

private int port;

/**

* 1.redis的控制器,操作redis

*/

public RedisManager redisManager() {

RedisManager redisManager = new RedisManager();

redisManager.setHost(host);

redisManager.setPort(port);

return redisManager;

}

/**

* 2.sessionDao

*/

public RedisSessionDAO redisSessionDAO() {

RedisSessionDAO sessionDAO = new RedisSessionDAO();

sessionDAO.setRedisManager(redisManager());

return sessionDAO;

}

/**

* 3.会话管理器

*/

public DefaultWebSessionManager sessionManager() {

CustomerSessionManager sessionManager = new CustomerSessionManager();

sessionManager.setSessionDAO(redisSessionDAO());

return sessionManager;

}

/**

* 4.缓存管理器

*/

public RedisCacheManager cacheManager() {

RedisCacheManager redisCacheManager = new RedisCacheManager();

redisCacheManager.setRedisManager(redisManager());

return redisCacheManager;

}

}

5、AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, pwd, getName());

这里的user对象要实现 Serializable ,AuthCachePrincipal两个接口

public class UserInfo implements Serializable,AuthCachePrincipal {

private Long id;

private String username;

private String password;

public Long getId() {

return id;

}

public void setId(Long id) {

this.id = id;

}

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

//从写getAuthCacheKey方法即可

@Override

public String getAuthCacheKey() {

return null;

}

 

以上是 shiro介绍和使用 的全部内容, 来源链接: utcz.com/z/516447.html

回到顶部