• Spring Boot 添加Shiro支持


    前言:

      Shiro是一个权限、会话管理的开源Java安全框架;Spring Boot集成Shiro后可以方便的使用Session;

    工程概述:

    (工程结构图)

    一、建立Spring Boot工程

      参照http://www.cnblogs.com/liangblog/p/5207855.html 建立一个SpringBoot工程;

    二、修改pom.xml,引入所需jar包

    <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.ddd</groupId>
      <artifactId>programme</artifactId>
      <version>0.0.1</version>
      <packaging>jar</packaging>
    
      <name>programme</name>
      <url>http://maven.apache.org</url> 
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      </properties>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.4.2.RELEASE</version>
        </parent>
    
      <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-commons</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jdbc-core</artifactId>
            <version>1.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpmime</artifactId>
            </dependency>
        <dependency>
                  <groupId>mysql</groupId>
                  <artifactId>mysql-connector-java</artifactId>
              </dependency>
              <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jdbc</artifactId>
            </dependency>
    
    
              <dependency>
                  <groupId>javax</groupId>
                  <artifactId>javaee-api</artifactId>
                  <version>7.0</version>
              </dependency>
              <dependency>
                  <groupId>org.apache.shiro</groupId>
                  <artifactId>shiro-spring</artifactId>
                  <version>1.2.3</version>
              </dependency>
              <dependency>
                  <groupId>org.apache.shiro</groupId>
                  <artifactId>shiro-cas</artifactId>
                  <version>1.2.3</version>
              </dependency>
              <dependency>
                  <groupId>org.apache.shiro</groupId>
                  <artifactId>shiro-ehcache</artifactId>
                  <version>1.2.3</version>
              </dependency>
              <dependency>
                  <groupId>org.springframework</groupId>
                  <artifactId>spring-jdbc</artifactId>
                  </dependency>
              <dependency>
                  <groupId>org.apache.shiro</groupId>
                  <artifactId>shiro-core</artifactId>
                  <version>1.2.3</version>
              </dependency>
              <dependency>
                  <groupId>org.apache.shiro</groupId>
                  <artifactId>shiro-web</artifactId>
                  <version>1.2.3</version>
              </dependency>
              <dependency>
                  <groupId>org.jasig.cas.client</groupId>
                  <artifactId>cas-client-core</artifactId>
                  <version>3.4.1</version>
              </dependency>
      </dependencies>
      
       <!-- Package as an executable jar -->
        <build>
            <defaultGoal>compile</defaultGoal>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
        <!-- Add Spring repositories -->
        <!-- (you don't need this if you are using a .RELEASE version) -->
         <!--    
             <repositories>
            <repository>
                <id>spring-snapshots</id>
                <url>http://repo.spring.io/snapshot</url>
                <snapshots><enabled>true</enabled></snapshots>
            </repository>
            <repository>
                <id>spring-milestones</id>
                <url>http://repo.spring.io/milestone</url>
            </repository>
        </repositories>
        <pluginRepositories>
            <pluginRepository>
                <id>spring-snapshots</id>
                <url>http://repo.spring.io/snapshot</url>
            </pluginRepository>
            <pluginRepository>
                <id>spring-milestones</id>
                <url>http://repo.spring.io/milestone</url>
            </pluginRepository>
        </pluginRepositories> 
        -->
      
    </project>
    pom.xml

      主要引入日志、数据库,shrio相关的jar包

    三、添加配置文件和日志文件

          配置文件需要放到resource文件夹下(指向classpath),并取名aplication.properties,工程会自动查找到文件配置信息

      配置文件:

    displayname = pm
    
    server.port=8011
    server.session.timeout=1000
    server.tomcat.uri-encoding=UTF-8
    
    spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test
    spring.datasource.username=root
    spring.datasource.password=123456
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    spring.datasource.max-idle=10
    spring.datasource.max-wait=10000
    spring.datasource.min-idle=5
    spring.datasource.initial-size=5
    
    logging.config=classpath:pm-logback.xml
    logging.path=log

      日志文件:

    <configuration scan="true" scanPeriod="10 seconds">
        <include resource="org/springframework/boot/logging/logback/base.xml" />
        <!-- 日志的级别:debug,info,warn,error -->
        <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <!--         
            <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                <level>DEBUG</level>
            </filter>
            
     -->     
             <File>${LOG_PATH}/info.log</File>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${LOG_PATH}/pm-info-%d{yyyyMMdd}.log.%i</fileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>100MB</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
                <maxHistory>2</maxHistory>
            </rollingPolicy>
            <layout class="ch.qos.logback.classic.PatternLayout">
                <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n
                </Pattern>
            </layout>
        </appender>
    
        <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                <level>ERROR</level>
            </filter>
            <File>${LOG_PATH}/error.log</File>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${LOG_PATH}/pm-error-%d{yyyyMMdd}.log.%i
                </fileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>100MB</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
                <maxHistory>2</maxHistory>
            </rollingPolicy>
            <layout class="ch.qos.logback.classic.PatternLayout">
                <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n
    
                </Pattern>
            </layout>
        </appender>
        <root level="INFO">
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="ERROR_FILE" />
        </root>
        
    </configuration>
    pm-logback.xml

      部署工程时可以放到工程jar所在文件夹内,部署的工程会自动找到文件;

    四、添加Shiro支持功能:

      1、新建shiro配置类,Shiro的主要配置信息都在此文件内实现;

    package com.ddd.program.config;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    import org.apache.shiro.cache.ehcache.EhCacheManager;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.session.SessionListener;
    import org.apache.shiro.session.mgt.SessionManager;
    import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class ShiroConfiguration {
    
        /**
         * ShiroFilterFactoryBean 处理拦截资源文件问题。
         * 注意:单独一个ShiroFilterFactoryBean配置是或报错的
         * 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager
         */
        @Bean
        public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    
            // 必须设置 SecurityManager
            shiroFilterFactoryBean.setSecurityManager(securityManager);
    
            // 拦截器.
            Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
    
            //filterChainDefinitionMap.put("/page/*", "authc");
            // 配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了
            //filterChainDefinitionMap.put("/security/logoff", "logout");
            
            shiroFilterFactoryBean.setLoginUrl("/#/login");
            // 未授权界面;
            shiroFilterFactoryBean.setUnauthorizedUrl("/403");
            
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
            
            return shiroFilterFactoryBean;
        }
    
        @Bean
        public SecurityManager securityManager() {
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            MyRealm myRealm = new MyRealm();
            securityManager.setRealm(myRealm);
            securityManager.setSessionManager(sessionManager());
            securityManager.setCacheManager(ehCacheManager());
            return securityManager;
        }
    
        @Bean
        public SessionManager sessionManager() {
            DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
            Collection<SessionListener> listeners = new ArrayList<SessionListener>();
            listeners.add(new MySessionListener());
            sessionManager.setSessionListeners(listeners);
            return sessionManager;
        }
    
        @Bean
        public EhCacheManager ehCacheManager() {
            EhCacheManager ehCacheManager = new EhCacheManager();
            //ehCacheManager.setCacheManagerConfigFile("classpath:encache.xml");
            return ehCacheManager;
        }
    
    }

      2、新建登录验证和Session监听的类(上面的类所需要的两个类)

        登录相关:

    package com.ddd.program.config;
    
    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.UnknownAccountException;
    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.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import com.cdv.nsite.program.model.AppUser;
    import com.cdv.nsite.program.services.impl.AppUserServiceImpl;
    
    public class MyRealm extends AuthorizingRealm {
    
        private final static Logger logger = LoggerFactory.getLogger(MyRealm.class);
        
        
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            logger.debug("登录验证后进行权限认证....");
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            return info;
        }
    
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            logger.debug("登录操作进行登录认证......");
            UsernamePasswordToken  token = (UsernamePasswordToken)authenticationToken;
    
            AppUser user = SpringContextUtils.getBean(AppUserServiceImpl.class).getUserByName(token.getUsername());
            if (user == null) {
                // 没找到帐号
                throw new UnknownAccountException(
                        "没有在本系统中找到对应的用户信息。");
            }
            //简单验证
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(
                    user.getUsername(),user.getPassword(),getName());
            
            return info;
        }
    
    }
    MyRealm.java

        Session相关:

    package com.ddd.program.config;
    
    import java.util.concurrent.atomic.AtomicInteger;
    
    import org.apache.shiro.session.Session;
    import org.apache.shiro.session.SessionListener;
    import org.springframework.stereotype.Component;
    
    @Component
    public class MySessionListener implements SessionListener {
    
        private final AtomicInteger sessionCount = new AtomicInteger(0);
        
        @Override
        public void onStart(Session session) {
            sessionCount.incrementAndGet();
            System.out.println("登录+1=="+sessionCount.get());
        }
    
        @Override
        public void onStop(Session session) {
            sessionCount.decrementAndGet();
            System.out.println("登录退出-1=="+sessionCount.get());
        }
    
        @Override
        public void onExpiration(Session session) {
            sessionCount.decrementAndGet();
            System.out.println("登录过期-1=="+sessionCount.get());
            
        }
    
        public int getSessionCount() {
            return sessionCount.get();
        }
    }
    MySessionListener.java

      3、添加静态页面:

        在resource文件夹下新建static或public文件夹,工程会默认找static文件夹下的index.*,没有在找public文件夹下的index.*;

      4、新建登录的接口和实现

       完整代码---> https://github.com/liangguang/springboot_18

    结述:

      以上代码只是个例子,主要是获得登录的Session用作其他用途;

    ---------------------------------------------------添加热部署支持-----------------------

      <!-- 模板引擎 暂时不用 -->
             <!--  <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
              </dependency> -->
            <!-- 
                devtools可以实现热部署。devtools会监听classpath下的文件变动,并且会立即重启应用(发生在保存时机),注意:因为其采用的虚拟机机制,该项重启是很快的
                如果设置SpringApplication.setRegisterShutdownHook(false),则自动重启将不起作用。
                设置 spring.devtools.restart.enabled 属性为false,可以关闭该特性。
             -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <optional>true</optional>
                <!-- optional=true,依赖不会传递,-->
            </dependency>
    添加devtools依赖
    spring.devtools.restart.enabled = true

    application.properties中添加配置项;

  • 相关阅读:
    有关 Windows 安全的一些记录
    常用的 PowerShell 脚本命令记录
    FireDAC 数据库开发笔记(2. 快储机制)
    FireDAC 数据库开发笔记(3. 使用内存数据 FDMemTable)
    FireDAC 数据库开发笔记(4. FireDAC 进阶)
    FireDAC 数据库开发笔记( 目录)
    FireDAC 数据库开发笔记(1. 处理数据)
    navicat连接sqlserver报错:[navicat premium] [IM002] [Microsoft][ODBC 驱动程序管理器] 未发现数据源名称并且未指定默认驱动程序
    利用分层机制优化 Docker Image
    重要参考步骤ProxySQL Cluster 集群搭建步骤
  • 原文地址:https://www.cnblogs.com/liangblog/p/6086798.html
Copyright © 2020-2023  润新知