Shiro笔记

145 阅读11分钟

这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

思维导图

写的不全,写了大概

Shiro.png

Shiro简介

Apache Shiro是一个强大的并且简单使用的java权限框架.主要应用认证(Authentication),授权(Authorization),cryptography(加密),和Session Manager.Shiro具有简单易懂的API,使用Shiro可以快速并且简单的应用到任何应用中,无论是从最小的移动app到最大的企业级web应用都可以使用.

核心功能

在Shiro官网首页上占用了很大的篇幅说明了Shiro的核心功能。

Authentication 认证。如用户的登录。

Authorization 授权。用户是否有权限访问指定URL等。

Cryptography 密码学。如密码的加密。

Session Management Session 管理。

Web Integration Web集成。Shiro不依赖于容器。

ShiroFeatures.png

参考文献:shiro.apache.org/introductio…

架构

Shiro架构图.png

以下是个人理解:

Subject(主体):用户交互信息

Authenticator(认证器):认证器,用户认证

Authorizer(授权器):权限和角色的管理

SessionManager: HttpSession对象 由shiro Session管理

Session DAO : 操作session内容

CacheManager:缓存管理,如用户凭证,角色,权限信息的管理

Realm:授权,身份验证,从数据库获取用户信息对 权限校验,身份校验,角色校验

Cryptography(密码学):对用户密码进行加密,提高安全性

架构详细信息可以参考:shiro.apache.org/architectur…

Shiro 的INI文件配置

INI英文名称(InitializationFile)

INI文件是Window系统配置文件的扩展名.

Shiro的全局配置文件就是.ini文件,ini中数据都是固定数据,后面会用数据库中数据

Shiro 的INI文件配置 分为四个部分

  • [main] 配置类对象,或设置属性等操作.

  • [users] 定义用户,密码及用户可以具有的角色

  • [roles] 定于角色具有的权限

  • [urls] 过滤器配置

实际开发中很少使用,这个了解一下就好了

Shiro注解

@RequiresPermissions 必须具有指定权限 @RequiresAuthentication 必须已经认证 @RequiresRoles 必须具有指定角色

@RequiresUser 必须是已认证或记住用户 @RequiresGuest 必须是访客

SpringBoot 整合 shiro

实现流程:

  • 1.搭建Manve项目
  • 2.导入依赖
  • 3.编写代码
  • 4.编写配置

这里就不演示了,提供依赖供参考

 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.13.RELEASE</version>
    </parent>

    <dependencies>
        <!--shiro集成了tomcat-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring-boot-web-starter</artifactId>
            <version>1.4.2</version>
        </dependency>
        <!--springBoot 整合thymeleaf-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <!--shiro 整合 thymeleaf  方便页使用权限验证-->
        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>

        <!--ehcache 做缓存-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>1.4.2</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>

        <!--mybatis的启动器-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>

        <!--数据库的驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.11</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!--测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

      </dependencies>

配置文件

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/shiro?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
    username: root
    password: root
shiro:
  loginUrl: /login  #用户没有登录跳转路径
server:
  port: 80

MD5 加密技术

public class TestMD5 {
    public static void main(String[] args) {

        Md5Hash md5Hash = new Md5Hash("test");
        System.out.println(md5Hash.toHex());

        /*加盐: 在密码中混入与密码不相干字符,提高密码解密难度*/
        Md5Hash md5Hash2 = new Md5Hash("test", "abcd");
        System.out.println(md5Hash2.toHex());

        /*迭代次数:加密次数*/
        Md5Hash md5Hash3 = new Md5Hash("test", "test", 2);
        System.out.println(md5Hash3.toHex());
    }
}

Shiro 整合 Thymeleaf 中的属性

shiro:user:认证通过或已记住的用户

shiro:authenticated :认证通过的用户。不包含记住的用户

shiro:principal :输出认证用户信息

shiro:hasRole :判断是否具有指定角色

shiro:lacksRole: 判断是否不具有指定角色

shiro:hasAllRoles:判断指定角色用户是否都具有

shiro:hasAnyRoles: 只要用户具有其中一个角色就表示判断通过。

shiro:hasPermission:是否具有指定权

shiro:lacksPermission:是否不具有指定权限

shiro:hasAllPermissions:是否全具有指定权限

shiro:hasAnyPermissions:只要有其中任何一个权限即可

示例

  <a shiro:hasRole="role1" href="/demo1">角色认证</a>
  <a shiro:hasPermission="sys:update" href="/demo2">权限认证</a>

Shiro过滤器规则

anon:不认证也可以访问。例如:/admin/**=anon /login=anon

authc:必须认证。 /**=authc ---所有的资源都认证

authcBasic:没有参数时表示httpBasic认证(客户端认证方式)。

logout:退出。

noSessionCreation:新增Filter,表示没有Session创建。

perms:判断是有具有指定权限。例如:/admin/user/**=perms[“per1”,”per2”]。必须同时具有给定权限才

可以访问。如果只有一个权限可以省略双引号。

port:限制端口。例如:/admin/**=port[8081]。只要请求不是8081端口就重新发送URL到8081端口。

rest:请求方式和权限的简便写法。例如:/admin/** =rest[user],相当于/admin/** = perms[user:方式],

方式是http请求的方式:post、get等。

roles:判断是否具有指定角色。/admin/**=roles[role1]

ssl:表示是安全的请求。协议为https

user:表示必须存在用户。

认证(登录实现)

实现流程:

  • 1.获取用户身份信息,通过Subject获取
  • 2.将用户身份信息,通过Authenticator(认证器) 验证
  • 3.验证通过,允许登录,验证失败,跳回登录页面

Shiro认证流程.png

编写控制类

/**
     * 登录验证
     */
@RequestMapping("/doLogin")
public String login(String name, String pwd,HttpSession session) {

    /*获取主体*/
    Subject subject = SecurityUtils.getSubject();
    /*存储用户身份信息*/
    AuthenticationToken token = new UsernamePasswordToken(name, pwd);
    try {
        /*对用身份校验*/
        subject.login(token);
        System.out.println("登录成功");
        session.setAttribute("user", token.getPrincipal().toString());
        return "main";
    } catch (UnknownAccountException e) {
        System.out.println("账号不存在");
    } catch (IncorrectCredentialsException e) {
        System.out.println("密码错误");
    } catch (AuthenticationException e) {
        e.printStackTrace();
    }
    return "login";
}

自定义Realm,对用户名,密码验证

  • 查询用户信息

  • 自定义Realm ,对用户信息校验

    编写一个类 继承AuthorizingRealm

@Component
public class MyRealm2 extends AuthorizingRealm {
    @Autowired
    private UserService userService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    /**
     * 自定义身份认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        /*获取身份*/
        String principal = token.getPrincipal().toString();
        /*身份验证*/
        User login = userService.login(principal);
        if (login!=null){
            /*参数1:用户名,参数2:用户密码,参数3:盐值,参数4:真实名,没有什么用*/
            SimpleAuthenticationInfo info =
                    new SimpleAuthenticationInfo(principal, login.getPwd(),
                    ByteSource.Util.bytes(login.getSalt()), "test");
            return info;
        }
        return null;
    }
}

编写配置类

  • 设置加密类型
  • shiro 过滤器配置
@Configuration
public class Config2 {
    @Autowired
    private MyRealm2 myRealm2;
    /*配置SecurityManager*/
    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        /*设置加密*/
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("md5");/*加密类型*/
        matcher.setHashIterations(2);/*迭代次数*/
        myRealm2.setCredentialsMatcher(matcher);

        securityManager.setRealm(myRealm2); /*设置自定义realm*/
        return securityManager;
    }


    /*配置过滤器*/
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();

        definition.addPathDefinition("/doLogin", "anon");  /*配置登录放行路径*/
        definition.addPathDefinition("/login", "anon"); /*配置登录放行路径*/
        definition.addPathDefinition("/**", "authc"); /*配置登录成功后放行路径*/
        definition.addPathDefinition("/**", "user");
        return definition;
    }
}    

RememberMe(记住我)

  • 前台传参 记住我
  • 后台处理
  • 配置RememberMe

修改登录控制单元方法

    /**
     * 登录验证
     */
@RequestMapping("/doLogin")
public String login(String name, String pwd, boolean remanaberMe, HttpSession session) {
    /*获取主体*/
    Subject subject = SecurityUtils.getSubject();
    /*存储用户身份信息*/
    AuthenticationToken token = new UsernamePasswordToken(name, pwd, remanaberMe);
    try {
        /*对用身份校验*/
        subject.login(token);
        System.out.println("登录成功");
        session.setAttribute("user", token.getPrincipal().toString());
        return "main";
    } catch (UnknownAccountException e) {
        System.out.println("账号不存在");
    } catch (IncorrectCredentialsException e) {
        System.out.println("密码错误");
    } catch (AuthenticationException e) {
        e.printStackTrace();
    }
    return "login";
}

配置类编写记住我

@Configuration
public class Config2 {
    @Autowired
    private MyRealm2 myRealm2;

    /*配置SecurityManager*/
    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        /*设置加密*/
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("md5");/*加密类型*/
        matcher.setHashIterations(2);/*迭代次数*/
        myRealm2.setCredentialsMatcher(matcher);

        securityManager.setRealm(myRealm2); /*设置自定义realm*/
        securityManager.setRememberMeManager(rememberMeManager());/*设置记住我*/
        return securityManager;
    }


    /*配置过滤器*/
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();

        definition.addPathDefinition("/doLogin", "anon");  /*配置登录放行路径*/
        definition.addPathDefinition("/login", "anon"); /*配置登录放行路径*/
        definition.addPathDefinition("/**", "authc"); /*配置登录成功后放行路径*/
        definition.addPathDefinition("/**", "user");
        return definition;
    }

    /**
     * 设置cookie
     */
    public SimpleCookie rememberCookieManager() {
        SimpleCookie cookie = new SimpleCookie();
        cookie.setName("test");/*设置cookie名称*/
        cookie.setPath("/"); /*cookie有效路径*/
        cookie.setHttpOnly(true);
        cookie.setMaxAge(30 * 24 * 60 * 60);/*cookie有效时间*/
        return cookie;
    }

    public CookieRememberMeManager rememberMeManager() {
        CookieRememberMeManager cookieRememberMeManager 
            = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberCookieManager());
        cookieRememberMeManager.setCipherKey("1234567890123".getBytes());/*cookie加密*/
        return cookieRememberMeManager;
    }
}    

退出登录实现

  • 控制层编写退出控制单元
  • 配置过滤器退出登录路径

编写退出控制单元

    @RequestMapping("/loginOut")
    public String loginOut() {
        return "login";
    }

配置类配置退出路径

@Configuration
public class Config2 {
    @Autowired
    private MyRealm2 myRealm2;

    /*配置SecurityManager*/
    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        /*设置加密*/
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("md5");/*加密类型*/
        matcher.setHashIterations(2);/*迭代次数*/
        myRealm2.setCredentialsMatcher(matcher);

        securityManager.setRealm(myRealm2); /*设置自定义realm*/
        securityManager.setRememberMeManager(rememberMeManager());/*设置记住我*/
        return securityManager;
    }


    /*配置过滤器*/
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();

        definition.addPathDefinition("/doLogin", "anon");  /*配置登录放行路径*/
        definition.addPathDefinition("/login", "anon"); /*配置登录放行路径*/
        definition.addPathDefinition("/loginOut", "logout"); /*配置退出登录路径*/
        definition.addPathDefinition("/**", "authc"); /*配置登录成功后放行路径*/
        definition.addPathDefinition("/**", "user");
        return definition;
    }

    /**
     * 设置cookie
     */
    public SimpleCookie rememberCookieManager() {
        SimpleCookie cookie = new SimpleCookie();
        cookie.setName("test");/*设置cookie名称*/
        cookie.setPath("/"); /*cookie有效路径*/
        cookie.setHttpOnly(true);
        cookie.setMaxAge(30 * 24 * 60 * 60);/*cookie有效时间*/
        return cookie;
    }

    public CookieRememberMeManager rememberMeManager() {
        CookieRememberMeManager cookieRememberMeManager 
            = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberCookieManager());
        cookieRememberMeManager.setCipherKey("1234567890123".getBytes());/*cookie加密*/
        return cookieRememberMeManager;
    }
}   

授权

  • 查询用户角色 、查询用户的权限

  • 编写自定义的Realm类

  • 编写角色控制和权限控制的单元

  • Shiro整合Thymeleaf页面控制授权, 用户是否显示按钮

Shiro授权流程.png

编写自定义Realm,处理授权

@Component
public class MyRealm2 extends AuthorizingRealm {

    @Autowired
    private UserService userService;
    /**
     * 自定义权限认证
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        /*获取身份*/
        String principal = principalCollection.getPrimaryPrincipal().toString();

        /*获取用户角色*/
        List<String> roles = userService.findRole(principal);
        /*获取用户权限*/
        List<String> permissions = userService.findPermission(principal);

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addRoles(roles);    /*给用户添加角色信息*/
        info.addStringPermissions(permissions);   /*给用户添加权限信息*/
        return info;
    }

    /**
     * 自定义身份认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        /*获取身份*/
        String principal = token.getPrincipal().toString();
        /*身份验证*/
        User login = userService.login(principal);
        if (login!=null){

            /*参数1:用户名,参数2:用户密码,参数3:盐值,参数4:真是名,没有什么用*/
            SimpleAuthenticationInfo info =
                    new SimpleAuthenticationInfo(principal, login.getPwd(),
                    ByteSource.Util.bytes(login.getSalt()), "test");
            return info;
        }
        return null;
    }
}

使用授权注解编写角色控制单元

/**
  * 角色认证测试
  */
@RequiresRoles("role1")
@ResponseBody
@RequestMapping("/demo1")
public String demo1() {
    return "角色认证测试";
}

使用授权注解编写权限控制单元

    /**
     * 权限认证测试
     */
    @RequiresPermissions("sys:update")
    @ResponseBody
    @RequestMapping("/demo2")
    public String demo2() {
        return "demo2";
    }

配置shiro 跟 thymeleaf 页面权限验证

/*配置shiro 跟 thymeleaf 页面权限验证*/
@Bean
public ShiroDialect shiroDialect() {
    return new ShiroDialect();
}

Thymeleaf页面权限控制

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
    <meta charset="UTF-8">
    <title>主页面</title>
</head>
<body>
    欢迎<span th:text="${session.user}"></span>
    <br>
    <a href="/loginOut">退出</a>  <br>
    <a shiro:hasRole="role1" href="/demo1">角色认证</a>
    <a shiro:hasPermission="sys:update" href="/demo2">权限认证</a>
</body>
</html>

缓存管理

这里用Ehcache 做Shiro 的缓存

  • 编写Ehcache配置文件
  • 配置类配置Shiro缓存

Ehcache配置文件

maxElementsInMemory:缓存中允许创建的最大对象数。

eternal:缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期。

timeToIdleSeconds:缓存数据的钝化时间,取值0表示无限长。

timeToLiveSeconds:缓存数据的生存时间,取值0表示无限长。

overflowToDisk:内存不足时,是否启用磁盘缓存。

memoryStoreEvictionPolicy:缓存满了之后的淘汰算法。

<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="ehcache" updateCheck="false">

    <!-- 磁盘缓存位置 -->
    <diskStore path="java.io.tmpdir"/>
    <!-- 默认缓存 -->
    <defaultCache
            maxEntriesLocalHeap="1000"
            eternal="false"
            timeToIdleSeconds="3600"
            timeToLiveSeconds="3600"
            overflowToDisk="false">
    </defaultCache>

    <!-- 记录用户的授权信息的缓存:缓存用户的角色和权限 -->
    <cache name="authorizationInfo"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="600"
           timeToLiveSeconds="0"
           overflowToDisk="false"
           statistics="true">
    </cache>
</ehcache>

Shiro配置类 设置缓存

shiro 会自动管理 EhCacheManager 对用户信息进行缓存

@Configuration
public class Config2 {
    @Autowired
    private MyRealm2 myRealm2;

    /*配置SecurityManager*/
    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        /*设置加密*/
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("md5");/*加密类型*/
        matcher.setHashIterations(2);/*迭代次数*/
        myRealm2.setCredentialsMatcher(matcher);

        securityManager.setRealm(myRealm2); /*设置自定义realm*/
        securityManager.setRememberMeManager(rememberMeManager());/*设置记住我*/
        securityManager.setCacheManager(ehCacheManager());/*设置缓存管理*/
        return securityManager;
    }


    /*配置过滤器*/
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();

        definition.addPathDefinition("/doLogin", "anon");  /*配置登录放行路径*/
        definition.addPathDefinition("/login", "anon"); /*配置登录放行路径*/
        definition.addPathDefinition("/loginOut", "logout"); /*配置退出登录路径*/
        definition.addPathDefinition("/**", "authc"); /*配置登录成功后放行路径*/
        definition.addPathDefinition("/**", "user");
        return definition;
    }

    /**
     * 设置cookie
     */
    public SimpleCookie rememberCookieManager() {
        SimpleCookie cookie = new SimpleCookie();
        cookie.setName("test");/*设置cookie名称*/
        cookie.setPath("/"); /*cookie有效路径*/
        cookie.setHttpOnly(true);
        cookie.setMaxAge(30 * 24 * 60 * 60);/*cookie有效时间*/
        return cookie;
    }

    public CookieRememberMeManager rememberMeManager() {
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberCookieManager());
        cookieRememberMeManager.setCipherKey("1234567890123".getBytes());/*cookie加密*/
        return cookieRememberMeManager;
    }


    /*配置shiro 跟 thymeleaf 页面权限验证*/
    @Bean
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }


    /*配置缓存*/
    public EhCacheManager ehCacheManager() {
        EhCacheManager ehCacheManager = new EhCacheManager();
        InputStream is = null;
        try {
            is = ResourceUtils.getInputStreamForPath("classpath:ehcache/ehcache-shiro.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        net.sf.ehcache.CacheManager cacheManager = new net.sf.ehcache.CacheManager(is);
        ehCacheManager.setCacheManager(cacheManager);
        return ehCacheManager;
    }
}

账号锁定

实现思路

  • 将用户密码输出次数标记
  • 存入缓存中
  • 判断登录次数,进行锁定
  • 缓存一定时间失效,用户可以再次登录

自定义凭证匹配

@Component
public class MyMatcher extends HashedCredentialsMatcher {

    private Ehcache passwordRetryEhcache;

    //声明构造方法获取缓存对象
    public MyMatcher(EhCacheManager ehCacheManager) {
        passwordRetryEhcache = ehCacheManager.getCacheManager().getCache("authorizationInfo");
    }
    
    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        //声明变量记录错误次数
        int i = 0;

        /*获取用户的登录次数的缓存信息*/

        //获取用户的身份信息(身份信息为缓存数据的键名)
        String username = token.getPrincipal().toString();
        System.out.println("账号锁定方法" + username);

        //获取缓存对象
        Element element = passwordRetryEhcache.get(username);
        /*判断是否有缓存数据*/
        if (element == null) {//没有缓存登录的错误次数,则创建新的缓存
            Element ele = new Element(username, new AtomicInteger(0));
            passwordRetryEhcache.put(ele);
        } else {
            /*有缓存直接递增*/
            AtomicInteger atomicInteger = (AtomicInteger) element.getObjectValue();
            i = atomicInteger.incrementAndGet();
        }
        System.out.println("登录认证失败次数:" + i);

        /*判断登录次数*/
        if (i >= 2) {
            System.out.println("登录次数过多");
            throw new ExcessiveAttemptsException();
        }
       /* 进行本次请求的登录*/
        boolean flag = super.doCredentialsMatch(token, info);

        if (flag) {
            passwordRetryEhcache.remove(username);
        }
        return flag;
    }
}

配置凭证匹配

@Configuration
public class Config2 {
    @Autowired
    private MyRealm2 myRealm2;

    @Autowired
    private MyMatcher myMatcher;

    /*配置SecurityManager*/
    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

        /*设置加密*/
        myMatcher.setHashAlgorithmName("md5");/*加密类型*/
        myMatcher.setHashIterations(2);/*迭代次数*/
        myRealm2.setCredentialsMatcher(myMatcher);

        securityManager.setRealm(myRealm2); /*设置自定义realm*/
        securityManager.setRememberMeManager(rememberMeManager());/*设置记住我*/
        securityManager.setCacheManager(ehCacheManager());/*设置缓存管理*/
        return securityManager;
    }


    /*配置过滤器*/
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();

        definition.addPathDefinition("/doLogin", "anon");  /*配置登录放行路径*/
        definition.addPathDefinition("/login", "anon"); /*配置登录放行路径*/
        definition.addPathDefinition("/loginOut", "logout"); /*配置退出登录路径*/
        definition.addPathDefinition("/**", "authc"); /*配置登录成功后放行路径*/
        definition.addPathDefinition("/**", "user");
        return definition;
    }

    /**
     * 设置cookie
     */
    public SimpleCookie rememberCookieManager() {
        SimpleCookie cookie = new SimpleCookie();
        cookie.setName("test");/*设置cookie名称*/
        cookie.setPath("/"); /*cookie有效路径*/
        cookie.setHttpOnly(true);
        cookie.setMaxAge(30 * 24 * 60 * 60);/*cookie有效时间*/
        return cookie;
    }

    public CookieRememberMeManager rememberMeManager() {
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberCookieManager());
        cookieRememberMeManager.setCipherKey("1234567890123".getBytes());/*cookie加密*/
        return cookieRememberMeManager;
    }


    /*配置shiro 跟 thymeleaf 页面权限验证*/
    @Bean
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }


    /*配置缓存*/
    @Bean
    public EhCacheManager ehCacheManager() {
        EhCacheManager ehCacheManager = new EhCacheManager();
        InputStream is = null;
        try {
            is = ResourceUtils.getInputStreamForPath("classpath:ehcache/ehcache-shiro.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        net.sf.ehcache.CacheManager cacheManager = new net.sf.ehcache.CacheManager(is);
        ehCacheManager.setCacheManager(cacheManager);
        return ehCacheManager;
    }
}

SessionManager

通过Subject 获取Session ,跟HttpSession 用法一样

ShiroSession管理.jpg

获取Session

Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();