zoukankan      html  css  js  c++  java
  • 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中添加配置项;

  • 相关阅读:
    iOS resign code with App Store profile and post to AppStore
    HTTPS科普扫盲帖 对称加密 非对称加密
    appid 评价
    使用Carthage安装第三方Swift库
    AngularJS:何时应该使用Directive、Controller、Service?
    xcode7 The operation couldn't be completed.
    cocoapods pod install 安装报错 is not used in any concrete target
    xcode7 NSAppTransportSecurity
    learning uboot how to set ddr parameter in qca4531 cpu
    learning uboot enable protect console
  • 原文地址:https://www.cnblogs.com/liangblog/p/6086798.html
Copyright © 2011-2022 走看看