前言:
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>
主要引入日志、數據庫,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>
部署工程時可以放到工程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; } }
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(); } }
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>
spring.devtools.restart.enabled = true
application.properties中添加配置項;