Contents
  1. 1. 集成Shiro
    1. 1.1. ShiroConfig配置
    2. 1.2. 集成ehcache缓存
    3. 1.3. 引入shiro标签和路径的访问权限
  2. 2. 引入redis做集群的session共享
  3. 3. 使用redis集成shiro做session管理和权限缓存

源码:数据库里面有2个用户 huang/123456 admin用户 、 test/123456 vip用户
https://github.com/huangzhenshi/psm_SpringBoot

#
以前的一个传统的maven管理的web项目,改造成SpringBoot并且集成一些新框架

  1. 文件夹路径的改变
  • maven项目把静态资源文件堆在webapp下面就可以了
    改用SpringBoot之后,默认的静态文件,要放在 resources\static下面
  1. 老项目默认就可以直接用jsp啊
  • 引入maven依赖
  • 配置spring.mvc.view.prefix 和 suffix,这个很方便哎
  • 设置module(web resource directory 为 webapp即可),设置web的路径为 webapp,和引入maven dependence
<!--jsp页面使用jstl标签-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!--用于编译jsp-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
  1. 配置日志
  • 简单暴力,在resources文件夹下添加logback-spring.xml
  • 设置mysql 打印sql
    <?xml version="1.0" encoding="UTF-8"?>
    <configuration scan="true" scanPeriod="60 seconds" debug="false">
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
    <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
    </appender>
    <root level="debug">
    <appender-ref ref="console" />
    </root>
    <logger name="account_huang.dao" level="debug"/>
    </configuration>
  1. 设置热加载

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
    </dependency>
  2. 集成JPA
    https://blog.csdn.net/forezp/article/details/70545038

  • 引入jpa依赖
  • 配置jpa选项
  • 修改实体类,引入注解
  • 修改接口
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    spring.jpa.database-platform= org.hibernate.dialect.MySQL5Dialect
    jpa.hibernate.show-sql= true
    @lombok.Data
    @Entity
    @Table(name="fuser")
    public class User{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private String id;
    public interface UserMapper extends JpaRepository<User, Long>{
  1. 事务控制的支持
    直接在service实现类的方法上添加 @Transactional 即可,该方法是依赖了 jpa的jar包,或者是jdbc的jar包里面的配置。

注意事项:

  • service必须是在接口层才有用啊,也是奇怪了。
  • mybatis的事务也受到JPA的控制,同一个父接口

集成Shiro

  • 引入jar包依赖
  • 配置ShiroConfig
  • 重写Realm
  • 引入表
  • 添加对应的实体类

ShiroConfig配置

  1. 过滤路径的变更,因为资源都在 /res路径下面的,设置了/res的不校验、和 WEB-INFO下的tld、tag文件的免验证
  2. 设置LoginUrl,进入程序自动跳转到登陆界面
  3. 对登陆校验路径进行免验证
  4. 设置没有权限的自动跳转页面
    @Configuration
    public class ShiroConfig {
    @Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
    System.out.println("ShiroConfiguration.shirFilter()");
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    shiroFilterFactoryBean.setSecurityManager(securityManager);
    //拦截器.
    Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
    // 配置不会被拦截的链接 顺序判断
    filterChainDefinitionMap.put("/static/**", "anon");
    filterChainDefinitionMap.put("/**/*.tag", "anon");
    filterChainDefinitionMap.put("/**/*.tld", "anon");
    filterChainDefinitionMap.put("/res/**", "anon");
    filterChainDefinitionMap.put("/loginCheck", "anon");
    shiroFilterFactoryBean.setLoginUrl("/login.do");
    //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
    filterChainDefinitionMap.put("/logout", "logout");
    filterChainDefinitionMap.put("/**", "authc");
    //未授权界面;
    shiroFilterFactoryBean.setUnauthorizedUrl("/403");
    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    return shiroFilterFactoryBean;
    }
    }

集成ehcache缓存

https://blog.csdn.net/snakemoving/article/details/77104217

  1. 引入两个jar包
  2. 在启动类中添加ehcache
  3. 添加对应的ehcache配置文件
    <dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-ehcache</artifactId>
    <version>1.2.2</version>
    </dependency>
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    </dependency>
    @Bean
    public EhCacheManager ehCacheManager(){
    System.out.println("ShiroConfiguration.getEhCacheManager()");
    EhCacheManager cacheManager = new EhCacheManager();
    cacheManager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
    return cacheManager;
    }
    @Bean
    public SecurityManager securityManager(){
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    securityManager.setCacheManager(ehCacheManager());//这个如果执行多次,也是同样的一个对象;
    securityManager.setRealm(myShiroRealm());
    return securityManager;
    }
    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://www.ehcache.org/ehcache.xsd">
    <diskStore path="java.io.tmpdir"/>
    <defaultCache
    maxElementsInMemory="10000"
    eternal="false"
    timeToIdleSeconds="120"
    timeToLiveSeconds="120"
    maxElementsOnDisk="10000000"
    diskExpiryThreadIntervalSeconds="120"
    memoryStoreEvictionPolicy="LRU">
    </defaultCache>
    </ehcache>

引入shiro标签和路径的访问权限

对系统配置的Code配置需要有admin管理权限

  1. 对CodeController整个模块进行权限控制

    @Controller
    @RequestMapping("/code")
    @RequiresRoles(value = "admin")
    public class CodeController{
  2. 对code配置的标签进行权限控制
    left-config.jsp里面进行配置

    <%@ taglib uri="http://shiro.apache.org/tags" prefix="shiro"%>
    <div class="F-left" style="width:100%;">
    <div class="PanelLeft F-left">
    <div class="BoxLeft">
    <img src="${ctx}/res/resource/style/images/icon01Hit.png" width="40" height="38" alt="" />
    <h4><b>系统配置</b></h4>
    </div>
    <div class="clear"></div>
    <div class="menuLeftFirst">
    <ul>
    <shiro:hasRole name="admin">
    <li id="configCodeNav" class="hit" onclick="refreshCenter('${ctx}/code/toMainRecordPage.do?username=${username}');" >
    <span>Code Config</span>
    </li>
    </shiro:hasRole>

引入redis做集群的session共享

  • nginx的负载均衡配置:
    http {
    include mime.types;
    default_type application/octet-stream;
    sendfile on;
    keepalive_timeout 65;
    upstream tomcatserver2 {
    server 127.0.0.1:8098;
    server 127.0.0.1:8099;
    }
    server {
    listen 80;
    server_name localhost;
    location / {
    proxy_pass http://tomcatserver2;
    proxy_redirect default;
    }
    }
    }
  1. 系统配置: maven依赖、引入相关bean(RedisSessionConfig 、RedisCacheConfig)、配置属性

    <!--redis-->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <!-- redis session -->
    <dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
    <version>1.3.1.RELEASE</version>
    </dependency>
    @Configuration
    @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 600)
    public class RedisSessionConfig {
    }
    spring.redis.host= 127.0.0.1
    spring.redis.port= 6379
    spring.redis.password= huangzs
    spring.redis.timeout= 0
    spring.redis.pool.max-idle=10
    spring.redis.pool.max-wait=3000
  2. 注意事项
    要redis缓存的 对象都要实现Serializable接口,否则会报错

使用redis集成shiro做session管理和权限缓存

参考博客,含有说明和源码
https://blog.csdn.net/liaoguolingxian/article/details/77017225

  1. 添加相关的工具类
  • ShiroRedisCache implements Cache {} 重写了 put get value size等方法
  • ShiroRedisCacheManager extends AbstractCacheManager{} 注入了ShiroRedisCache
  • RedisSessionDao 被sessionmanager引用,执行一些对session的管理,比如创建、更新等操作 RedisSessionDao redisSessionDao = new RedisSessionDao(redisTemplate);
  • MySessionIdGenerator 也是为了sessionmanager提供一个项目特色的id而已
  1. 修改Shiro-config
    @Bean(name = "myShiroRealm")
    @DependsOn(value = {"lifecycleBeanPostProcessor", "ShiroRedisCacheManager"})
    public MyShiroRealm myShiroRealm(RedisTemplate redisTemplate) {
    MyShiroRealm shiroRealm = new MyShiroRealm();
    shiroRealm.setCacheManager(redisCacheManager(redisTemplate));
    shiroRealm.setCachingEnabled(true);
    //认证
    shiroRealm.setAuthenticationCachingEnabled(false);
    //授权
    shiroRealm.setAuthorizationCachingEnabled(false);
    return shiroRealm;
    }
    @Bean
    public SecurityManager securityManager(RedisTemplate redisTemplate){
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    securityManager.setCacheManager(redisCacheManager(redisTemplate));
    securityManager.setRealm(myShiroRealm(redisTemplate));
    securityManager.setSessionManager(sessionManager(redisTemplate));
    return securityManager;
    }
    @Bean(name = "ShiroRedisCacheManager")
    public ShiroRedisCacheManager redisCacheManager(RedisTemplate redisTemplate) {
    ShiroRedisCacheManager redisCacheManager = new ShiroRedisCacheManager(redisTemplate);
    //name是key的前缀,可以设置任何值,无影响,可以设置带项目特色的值
    redisCacheManager.createCache("shiro_redis");
    return redisCacheManager;
    }
    @Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
    return new LifecycleBeanPostProcessor();
    }
    @Bean(name = "sessionManager")
    @DependsOn(value = "lifecycleBeanPostProcessor")
    public DefaultWebSessionManager sessionManager(RedisTemplate redisTemplate) {
    DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
    RedisSessionDao redisSessionDao = new RedisSessionDao(redisTemplate);
    //这个name的作用也不大,只是有特色的cookie的名称。
    redisSessionDao.setSessionIdGenerator(sessionIdGenerator("starrkCookie"));
    sessionManager.setSessionDAO(redisSessionDao);
    sessionManager.setDeleteInvalidSessions(true);
    SimpleCookie cookie = new SimpleCookie();
    cookie.setName("starrkCookie");
    sessionManager.setSessionIdCookie(cookie);
    sessionManager.setSessionIdCookieEnabled(true);
    return sessionManager;
    }
    public MySessionIdGenerator sessionIdGenerator(String name) {
    return new MySessionIdGenerator(name);
    }
Contents
  1. 1. 集成Shiro
    1. 1.1. ShiroConfig配置
    2. 1.2. 集成ehcache缓存
    3. 1.3. 引入shiro标签和路径的访问权限
  2. 2. 引入redis做集群的session共享
  3. 3. 使用redis集成shiro做session管理和权限缓存