您的位置:首页 > 编程语言 > Java开发

IntelliJ IDEA Spring Boot(6) 集成Hibernate+Shiro+Ehcache

2017-10-28 22:04 716 查看
   说真的用spring boot 集成集成Hibernate+Shiro+Ehcache。费了我老大的功夫啊。

  但这一切都是值得。

  1. 首先第一点,以前用xml配置shiro的,将失效。错误的说法,可以使用xml。

  2. 以前xml中配置的bean,请在加@Configuration注解的类中定义方法并加上注解  

      @Bean,最好写上name属性,不然以方法名命名bean的名字

 下面开始配置吧。

  第一: 集成hibernate。这一步骤,http://blog.csdn.net/u011998835/article/details/78369721已经介绍了。但是我稍微做一下修改。

   

@EnableTransactionManagement
@EnableCaching
@SpringBootApplication
public class SpringbootApplication {

public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}

}


这里不再定义SessionFactory的注入了。改成下面的方式

package com.dashuai.springboot.config;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManagerFactory;

@Configuration
public class SessionFactoryConfig {

@Autowired
private EntityManagerFactory entityManagerFactory;

@Bean(name="SessionFactory")
public SessionFactory getSessionFactory() {
if (entityManagerFactory.unwrap(SessionFactory.class) == null) {
throw new NullPointerException("factory is not a hibernate factory");
}
return entityManagerFactory.unwrap(SessionFactory.class);
}

}


还有就是我一直忽略的问题,这里补充一下,就是Druid数据源监控页面并没有配置。

这里新增一下。

package com.dashuai.springboot.config;

import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DruidConfig {

@Bean
public ServletRegistrationBean druidStatView() {
ServletRegistrationBean registration = new ServletRegistrationBean(new StatViewServlet());
registration.addUrlMappings("/druid/*");
return registration;
}

@Bean
public FilterRegistrationBean druidWebStatFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean(new WebStatFilter());
registration.addInitParameter("exclusions","/css/*,/style/*,/js/*,*.js,*.css,/druid*,/attached/*,*.jsp");
registration.addInitParameter("principalSessionName","sessionUser");
registration.addInitParameter("profileEnable","true");
registration.addUrlPatterns("/*");
registration.setOrder(1);
return registration;
}
}

这里@Bean我没有给name属性赋值,那么它的值就是 方法名字

其实上述代码就是以前web.xml中配置的如下代码的转换

<!-- //////////////阿里巴巴数据连接池 Druid的监控/////////////////// -->
<filter>
<filter-name>druidWebStatFilter</filter-name>
<filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
<init-param>
<param-name>exclusions</param-name>
<param-value>
/css/*,/style/*,/js/*,*.js,*.css,/druid*,/attached/*,*.jsp
</param-value>
</init-param>
<init-param>
<param-name>principalSessionName</param-name>
<param-value>sessionUser</param-value>
</init-param>
<init-param>
<param-name>profileEnable</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>druidWebStatFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- //////////druid监控页面,使用${pageContext.request.contextPath}/druid/index.html访问///////// -->
<servlet>
<servlet-name>druidStatView</servlet-name>
<servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>druidStatView</servlet-name>
<url-pattern>/druid/*</url-pattern>
</servlet-mapping>


上面的集成完毕之后,解析来集成shiro。

以前shiro是配置在 xml中,类似这样

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">

<!-- Realm 域 授权和认证的判断 -->
<bean id="systemUserRealm" class="com.dashuai.shiro.SystemUserRealm" />
<bean id="normalUserRealm" class="com.dashuai.shiro.NormalUserRealm" />
<!-- FormAuthenticationFilter -->
<bean id="systemAuthFilter" class="com.dashuai.shiro.SystemFormAuthFilter" >
<property name="loginUrl" value="/admin/login.html" />
<property name="successUrl" value="/admin/index.html" />
</bean>
<bean id="normalAuthFilter" class="com.dashuai.shiro.NormalFormAuthFilter" >
<property name="loginUrl" value="/login.html" />
<property name="successUrl" value="/index.html" />
</bean>

<bean id="defineModularRealmAuthenticator" class="com.dashuai.shiro.DefautModularRealm">
<property name="definedRealms">
<map>
<entry key="systemAuthorizingRealm" value-ref="systemUserRealm" />
<entry key="normalAuthorizingRealm" value-ref="normalUserRealm" />
</map>
</property>
<property name="authenticationStrategy">
<bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"></bean>
</property>
</bean>

<!-- 安全认证过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="filters">
<map>
<entry key="authsys" value-ref="systemAuthFilter"></entry>
<entry key="authnor" value-ref="normalAuthFilter"></entry>
</map>
</property>
<property name="filterChainDefinitions">
<value>
/res_admin/**=anon
/res_front/**=anon
/plugins/**=anon
/login.html=anon
/admin/login.*=anon
/admin/**=authsys
/user/**=authnor
/**=anon
</value>
</property>
</bean>

<!-- 定义Shiro安全管理配置 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="cacheManager" ref="memoryConstrainedCacheManager" />
<property name="authenticator" ref="defineModularRealmAuthenticator" />
<!-- 这里主要是设置自定义的单Realm应用,若有多个Realm,可使用'realms'属性代替 -->
<!-- <property name="realm" ref="loginRealm"/> -->
<property name="realms"  >
<list>
<ref bean="systemUserRealm" />
<ref bean="normalUserRealm"/>
</list>
</property>
<property name="sessionManager" ref="sessionManager" />
<property name="rememberMeManager" ref="rememberMeManager"/>
</bean>

<!-- 定义授权缓存管理器 -->
<bean id="shiroCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:ehcache.xml" />
</bean>

<bean id="memoryConstrainedCacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager" />

<!-- 自定义会话管理配置 -->
<!-- 指定本系统SESSIONID, 默认为: JSESSIONID 问题: 与SERVLET容器名冲突, 如JETTY, TOMCAT 等默认JSESSIONID,
当跳出SHIRO SERVLET时如ERROR-PAGE容器会为JSESSIONID重新分配值导致登录会话丢失! -->
<bean id="sessionManager"
class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<property name="sessionDAO" ref="sessionDAO" />
<!-- 会话超时时间,单位:毫秒 -->
<property name="globalSessionTimeout" value="1800000" />
<!-- 定时清理失效会话, 清理用户直接关闭浏览器造成的孤立会话 -->
<property name="sessionValidationInterval" value="1800000" />
<property name="sessionValidationSchedulerEnabled" value="true" />
<property name="sessionIdCookie" ref="simpleCookie" />
<property name="sessionIdCookieEnabled" value="true" />
</bean>

<!-- 会话Cookie模板 -->
<bean id="simpleCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg name="name" value="shiro.sesssion"/>
<property name="path" value="/"/>
</bean>

<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg value="rememberMe"/>
<property name="httpOnly" value="true"/>
<property name="maxAge" value="604800"/><!-- 7天 -->
</bean>

<!-- rememberMe管理器 -->
<bean id="rememberMeManager"
class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<property name="cipherKey"
value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}"/>
<property name="cookie" ref="rememberMeCookie"/>
</bean>

<bean id="sessionDAO"
class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
<property name="cacheManager" ref="shiroCacheManager" />
</bean>

<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />

</beans>


但是用springboot 就不能这样写了。应慢慢修改成对应下面的java代码,我也是很辛苦的一一对应的写上的。

package com.dashuai.springboot.config;

import com.dashuai.springboot.shiro.*;
import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;

import javax.servlet.Filter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

@Bean(name = "systemAuthFilter")
public SystemFormAuthFilter getSystemFormAuthFilter() {
SystemFormAuthFilter formAuthFilter = new SystemFormAuthFilter();
formAuthFilter.setSuccessUrl("/admin/index.html");
formAuthFilter.setLoginUrl("/admin/login.html");
return formAuthFilter;
}

@Bean(name = "normalAuthFilter")
public NormalFormAuthFilter getNormalFormAuthFilter() {
NormalFormAuthFilter formAuthFilter = new NormalFormAuthFilter();
formAuthFilter.setSuccessUrl("/index.html");
formAuthFilter.setLoginUrl("/login.html");
return formAuthFilter;
}

@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean getShiroFilterFactoryBean() {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(getDefaultWebSecurityManager());
Map<String, Filter> filters = new LinkedHashMap<>();
filters.put("authsys", getSystemFormAuthFilter());
filters.put("authnor", getNormalFormAuthFilter());
shiroFilterFactoryBean.setFilters(filters);
LinkedHashMap<String, String> filterChainDefinitionMap=new LinkedHashMap<>();
filterChainDefinitionMap.put("/login.html", "anon");
filterChainDefinitionMap.put("/admin/login.*", "anon");
filterChainDefinitionMap.put("/admin", "authsys");
filterChainDefinitionMap.put("/admin/", "authsys");
filterChainDefinitionMap.put("/admin/**.html", "authsys");// 也就是说 这个配置请细致配置
// filterChainDefinitionMap.put("/admin/**", "authsys");// 不可以加这个,否则/admin/login.*失效
filterChainDefinitionMap.put("/user/**", "authnor");
filterChainDefinitionMap.put("/**", "anon");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}

@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setCacheManager(getMemoryConstrainedCacheManager());
securityManager.setAuthenticator(getDefautModularRealm());
ArrayList<Realm> list = new ArrayList<>();
list.add(getSystemUserRealm());
list.add(getNormalUserRealm());
securityManager.setRealms(list);
securityManager.setSessionManager(getDefaultWebSessionManager());
securityManager.setRememberMeManager(getCookieRememberMeManager());
return securityManager;
}

@Bean(name = "memoryConstrainedCacheManager")
public MemoryConstrainedCacheManager getMemoryConstrainedCacheManager() {
MemoryConstrainedCacheManager manager = new MemoryConstrainedCacheManager();
return manager;
}

@Bean(name = "defineModularRealmAuthenticator")
public DefautModularRealm getDefautModularRealm() {
DefautModularRealm realm = new DefautModularRealm();
Map<String, Object> definedRealms = new HashMap<>();
definedRealms.put("systemAuthorizingRealm", getSystemUserRealm());
definedRealms.put("normalAuthorizingRealm", getNormalUserRealm());
realm.setDefinedRealms(definedRealms);
realm.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
return realm;
}

@Bean(name = "systemUserRealm")
public SystemUserRealm getSystemUserRealm() {
SystemUserRealm realm = new SystemUserRealm();
return realm;
}

@Bean(name = "normalUserRealm")
public NormalUserRealm getNormalUserRealm() {
NormalUserRealm realm = new NormalUserRealm();
return realm;
}

@Bean(name = "sessionManager")
public DefaultWebSessionManager getDefaultWebSessionManager() {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setSessionDAO(getEnterpriseCacheSessionDAO());
sessionManager.setGlobalSessionTimeout(1800000);
sessionManager.setSessionValidationInterval(1800000);
sessionManager.setSessionIdCookieEnabled(true);
sessionManager.setSessionValidationSchedulerEnabled(true);
sessionManager.setSessionIdCookie(getSimpleCookie());
return sessionManager;
}

@Bean(name = "sessionDAO")
public EnterpriseCacheSessionDAO getEnterpriseCacheSessionDAO() {
EnterpriseCacheSessionDAO sessionDAO = new EnterpriseCacheSessionDAO();
sessionDAO.setCacheManager(getEhCacheManager());
return sessionDAO;
}

@Bean(name = "shiroCacheManager")
public EhCacheManager getEhCacheManager() {
EhCacheManager em = new EhCacheManager();
em.setCacheManagerConfigFile("classpath:ehcache.xml");
return em;
}

@Bean(name = "simpleCookie")
public SimpleCookie getSimpleCookie() {
SimpleCookie simpleCookie = new SimpleCookie("shiro.sesssion");
simpleCookie.setPath("/");
return simpleCookie;
}

@Bean(name = "rememberMeManager")
public CookieRememberMeManager getCookieRememberMeManager() {
CookieRememberMeManager meManager = new CookieRememberMeManager();
meManager.setCipherKey(org.apache.shiro.codec.Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));
meManager.setCookie(getRememberMeCookie());
return meManager;
}

@Bean(name = "rememberMeCookie")
public SimpleCookie getRememberMeCookie() {
SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
simpleCookie.setHttpOnly(true);
simpleCookie.setMaxAge(604800); // 7天
return simpleCookie;
}
// 千万不要配置这个,这是导致Could not obtain transaction-synchronized Session for current thread产生的原因
// 至于为什么,弄不清楚
//    @Bean(name = "lifecycleBeanPostProcessor")
//    public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
//        return new LifecycleBeanPostProcessor();
//    }
@Bean public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean filterRegistration = new FilterRegistrationBean(); filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter")); filterRegistration.addInitParameter("targetFilterLifecycle", "true"); filterRegistration.addUrlPatterns("/*"); return filterRegistration; }}
基本上一一对应。但这里有两个个巨坑。

LinkedHashMap<String, String> filterChainDefinitionMap=new LinkedHashMap<>();
filterChainDefinitionMap.put("/login.html", "anon");
filterChainDefinitionMap.put("/admin/login.*", "anon");
filterChainDefinitionMap.put("/admin", "authsys");
filterChainDefinitionMap.put("/admin/", "authsys");
filterChainDefinitionMap.put("/admin/**.html", "authsys");// 也就是说 这个配置请细致配置
// filterChainDefinitionMap.put("/admin/**", "authsys");// 不可以加这个,否则/admin/login.*失效
filterChainDefinitionMap.put("/user/**", "authnor");
filterChainDefinitionMap.put("/**", "anon");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

就是url的拦截,请细致小心的配置,不要直接/**什么的,会导致最基本的登陆请求都完成不了,我就在这吃了大亏。因为在xml中那样配置没有问题,但是写成java代码,差点没坑死我。

 第二个坑,我找了好长好长时间。 因为上一篇只集成hibernate的时候,并没有报异常。Could not obtain transaction-synchronized Session for current thread

Could not obtain transaction-synchronized Session for current thread


可是加上ShiroConfig,怎么都报这个异常。刚开始使用配置openSessionInViewFilter,起点作用,但是在单元测试的时候,还是抱上述异常。我就非常纳闷,我尝试先关闭shiroConfig,然后发现单元测试就不报异常了。所以我觉得就是这个的配置,所以我基本一点点注释,才发现,一旦配置LifecycleBeanPostProcessor,一定报上述异常。

所以这个坑,哎~~~ 伤不起啊。

   忘了没有修改ehcache.xml中shiro的缓存设置了。

<!-- shiro ehcache-->
<!-- 登录记录缓存 锁定10分钟 -->
<cache name="passwordRetryCache"
maxElementsInMemory="2000" eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
<cache name="authorizationCache"
maxElementsInMemory="2000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
<cache name="authenticationCache"
maxElementsInMemory="2000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
<cache name="shiro-activeSessionCache"
maxElementsInMemory="2000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
<cache name="shiro_cache"
maxElementsInMemory="2000"
eternal="false"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
maxElementsOnDisk="0"
overflowToDisk="true"
memoryStoreEvictionPolicy="FIFO"
statistics="true">
</cache>

加上,然后我们运行起来。

log日志我也粘上来吧。

22:16:10.124 [main] DEBUG org.springframework.boot.devtools.settings.DevToolsSettings - Included patterns for restart : []
22:16:10.125 [main] DEBUG org.springframework.boot.devtools.settings.DevToolsSettings - Excluded patterns for restart : [/spring-boot-starter/target/classes/, /spring-boot-autoconfigure/target/classes/, /spring-boot-starter-[\w-]+/, /spring-boot/target/classes/, /spring-boot-actuator/target/classes/, /spring-boot-devtools/target/classes/]
22:16:10.126 [main] DEBUG org.springframework.boot.devtools.restart.ChangeableUrls - Matching URLs for reloading : [file:/E:/WorkSpace/springboot/target/classes/]

.   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/  ___)| |_)| | | | | || (_| |  ) ) ) )
'  |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot ::        (v1.5.8.RELEASE)

2017-10-28 22:16:10.323  INFO 5840 --- [  restartedMain] c.d.springboot.SpringbootApplication     : Starting SpringbootApplication on DESKTOP-I8M03ML with PID 5840 (E:\WorkSpace\springboot\target\classes started by yaoshuangshuai in E:\WorkSpace\springboot)
2017-10-28 22:16:10.324  INFO 5840 --- [  restartedMain] c.d.springboot.SpringbootApplication     : No active profile set, falling back to default profiles: default
2017-10-28 22:16:10.542  INFO 5840 --- [  restartedMain] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@7245da69: startup date [Sat Oct 28 22:16:10 CST 2017]; root of context hierarchy
2017-10-28 22:16:11.496  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'shiroConfig' of type [com.dashuai.springboot.config.ShiroConfig$$EnhancerBySpringCGLIB$$9b51ca65] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:11.658  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'memoryConstrainedCacheManager' of type [org.apache.shiro.cache.MemoryConstrainedCacheManager] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:11.692  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.devtools.autoconfigure.DevToolsDataSourceAutoConfiguration' of type [org.springframework.boot.devtools.autoconfigure.DevToolsDataSourceAutoConfiguration$$EnhancerBySpringCGLIB$$e5568eb1] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:11.694  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Generic' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Generic] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:11.777  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:11.810  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'dataSource' of type [com.alibaba.druid.pool.DruidDataSource] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:11.814  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'inMemoryDatabaseShutdownExecutor' of type [org.springframework.boot.devtools.autoconfigure.DevToolsDataSourceAutoConfiguration$NonEmbeddedInMemoryDatabaseShutdownExecutor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:11.828  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'spring.jpa-org.springframework.boot.autoconfigure.orm.jpa.JpaProperties' of type [org.springframework.boot.autoconfigure.orm.jpa.JpaProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:11.834  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration' of type [org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$$EnhancerBySpringCGLIB$$9f067a84] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:11.841  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'spring.transaction-org.springframework.boot.autoconfigure.transaction.TransactionProperties' of type [org.springframework.boot.autoconfigure.transaction.TransactionProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:11.844  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'platformTransactionManagerCustomizers' of type [org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:11.850  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration' of type [org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$7418e39a] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:11.864  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'jpaVendorAdapter' of type [org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:11.867  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'entityManagerFactoryBuilder' of type [org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:11.903  INFO 5840 --- [  restartedMain] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default'
2017-10-28 22:16:12.012 DEBUG 5840 --- [  restartedMain] o.h.c.internal.RegionFactoryInitiator    : Cache region factory : org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
2017-10-28 22:16:12.119  INFO 5840 --- [  restartedMain] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} inited
2017-10-28 22:16:12.362  WARN 5840 --- [  restartedMain] org.hibernate.id.UUIDHexGenerator        : HHH000409: Using org.hibernate.id.UUIDHexGenerator which does not generate IETF RFC 4122 compliant UUID values; consider using org.hibernate.id.UUIDGenerator instead
2017-10-28 22:16:12.527  INFO 5840 --- [  restartedMain] o.h.cache.spi.UpdateTimestampsCache      : HHH000250: Starting update timestamps cache at region: org.hibernate.cache.spi.UpdateTimestampsCache
2017-10-28 22:16:12.531  INFO 5840 --- [  restartedMain] o.h.cache.internal.StandardQueryCache    : HHH000248: Starting query cache at region: org.hibernate.cache.internal.StandardQueryCache
2017-10-28 22:16:12.594  WARN 5840 --- [  restartedMain] o.h.c.e.AbstractEhcacheRegionFactory     : HHH020003: Could not find a specific ehcache configuration for cache named [com.dashuai.springboot.entity.SystemUser]; using defaults.
2017-10-28 22:16:12.595 DEBUG 5840 --- [  restartedMain] o.h.c.e.AbstractEhcacheRegionFactory     : started EHCache region: com.dashuai.springboot.entity.SystemUser
2017-10-28 22:16:12.596  WARN 5840 --- [  restartedMain] c.e.i.s.EhcacheAccessStrategyFactoryImpl : HHH020007: read-only cache configured for mutable entity [com.dashuai.springboot.entity.SystemUser]
2017-10-28 22:16:12.638  WARN 5840 --- [  restartedMain] o.h.c.e.AbstractEhcacheRegionFactory     : HHH020003: Could not find a specific ehcache configuration for cache named [com.dashuai.springboot.entity.SystemRole]; using defaults.
2017-10-28 22:16:12.639 DEBUG 5840 --- [  restartedMain] o.h.c.e.AbstractEhcacheRegionFactory     : started EHCache region: com.dashuai.springboot.entity.SystemRole
2017-10-28 22:16:12.640  WARN 5840 --- [  restartedMain] c.e.i.s.EhcacheAccessStrategyFactoryImpl : HHH020007: read-only cache configured for mutable entity [com.dashuai.springboot.entity.SystemRole]
2017-10-28 22:16:12.917  INFO 5840 --- [  restartedMain] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2017-10-28 22:16:12.919  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'entityManagerFactory' of type [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:12.920  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'entityManagerFactory' of type [com.sun.proxy.$Proxy66] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:12.921  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'sessionFactoryConfig' of type [com.dashuai.springboot.config.SessionFactoryConfig$$EnhancerBySpringCGLIB$$e5b8db62] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:12.928  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'SessionFactory' of type [org.hibernate.internal.SessionFactoryImpl] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:12.929  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'systemUserDao' of type [com.dashuai.springboot.dao.impl.SystemUserDaoImpl] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:12.930  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'systemUserService' of type [com.dashuai.springboot.service.impl.SystemUserServiceImpl] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:12.930  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'systemUserRealm' of type [com.dashuai.springboot.shiro.SystemUserRealm] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:12.937  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'normalUserRealm' of type [com.dashuai.springboot.shiro.NormalUserRealm] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:12.940  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'defineModularRealmAuthenticator' of type [com.dashuai.springboot.shiro.DefautModularRealm] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:12.952  WARN 5840 --- [  restartedMain] net.sf.ehcache.CacheManager              : Creating a new instance of CacheManager using the diskStorePath "../springBoot_Ehcache" which is already used by an existing CacheManager.
The source of the configuration was net.sf.ehcache.config.generator.ConfigurationSource$InputStreamConfigurationSource@76292dc5.
The diskStore path for this CacheManager will be set to ../springBoot_Ehcache\ehcache_auto_created_1509200172951.
To avoid this warning consider using the CacheManager factory methods to create a singleton CacheManager or specifying a separate ehcache configuration (ehcache.xml) for each CacheManager instance.
2017-10-28 22:16:12.954  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'shiroCacheManager' of type [org.apache.shiro.cache.ehcache.EhCacheManager] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:12.958  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'sessionDAO' of type [org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:12.961  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'simpleCookie' of type [org.apache.shiro.web.servlet.SimpleCookie] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:12.968  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'sessionManager' of type [org.apache.shiro.web.session.mgt.DefaultWebSessionManager] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:12.970  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'rememberMeCookie' of type [org.apache.shiro.web.servlet.SimpleCookie] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:12.973  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'rememberMeManager' of type [org.apache.shiro.web.mgt.CookieRememberMeManager] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:12.978  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'securityManager' of type [org.apache.shiro.web.mgt.DefaultWebSecurityManager] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:12.986  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'systemAuthFilter' of type [com.dashuai.springboot.shiro.SystemFormAuthFilter] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:12.992  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'normalAuthFilter' of type [com.dashuai.springboot.shiro.NormalFormAuthFilter] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:13.027  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cache.annotation.ProxyCachingConfiguration' of type [org.springframework.cache.annotation.ProxyCachingConfiguration$$EnhancerBySpringCGLIB$$53a4b598] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:13.037  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration' of type [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration$$EnhancerBySpringCGLIB$$48187a3c] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:13.046  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'spring.cache-org.springframework.boot.autoconfigure.cache.CacheProperties' of type [org.springframework.boot.autoconfigure.cache.CacheProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:13.053  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'cacheManagerCustomizers' of type [org.springframework.boot.autoconfigure.cache.CacheManagerCustomizers] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:13.054  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration' of type [org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration$$EnhancerBySpringCGLIB$$e9b3ed1d] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:13.059  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'cacheManager' of type [org.springframework.cache.concurrent.ConcurrentMapCacheManager] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:13.059  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'cacheAutoConfigurationValidator' of type [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration$CacheManagerValidator] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:13.073  INFO 5840 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$a927f7a] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-10-28 22:16:13.322  INFO 5840 --- [  restartedMain] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2017-10-28 22:16:13.329  INFO 5840 --- [  restartedMain] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2017-10-28 22:16:13.330  INFO 5840 --- [  restartedMain] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.23
2017-10-28 22:16:13.401  INFO 5840 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2017-10-28 22:16:13.402  INFO 5840 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 2863 ms
2017-10-28 22:16:13.549  INFO 5840 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2017-10-28 22:16:13.550  INFO 5840 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2017-10-28 22:16:13.550  INFO 5840 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2017-10-28 22:16:13.550  INFO 5840 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2017-10-28 22:16:13.550  INFO 5840 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'webStatFilter' to urls: [/*]
2017-10-28 22:16:13.550  INFO 5840 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'openSessionInViewFilter' to urls: [/*]
2017-10-28 22:16:13.550  INFO 5840 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'delegatingFilterProxy' to urls: [/*]
2017-10-28 22:16:13.550  INFO 5840 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'systemAuthFilter' to: [/*]
2017-10-28 22:16:13.550  INFO 5840 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'normalAuthFilter' to: [/*]
2017-10-28 22:16:13.550  INFO 5840 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'shiroFilter' to: [/*]
2017-10-28 22:16:13.550  INFO 5840 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'statViewServlet' to [/druid/*]
2017-10-28 22:16:13.551  INFO 5840 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'dispatcherServlet' to [/]
2017-10-28 22:16:13.880  INFO 5840 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@7245da69: startup date [Sat Oct 28 22:16:10 CST 2017]; root of context hierarchy
2017-10-28 22:16:13.926  INFO 5840 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/admin/ || /admin/index.html]}" onto public java.lang.String com.dashuai.springboot.controller.AdminController.index()
2017-10-28 22:16:13.926  INFO 5840 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/admin]}" onto public java.lang.String com.dashuai.springboot.controller.AdminController.index2()
2017-10-28 22:16:13.927  INFO 5840 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/admin/login.html]}" onto public java.lang.String com.dashuai.springboot.controller.AdminController.loginIndex()
2017-10-28 22:16:13.928  INFO 5840 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/admin/login.do]}" onto public java.lang.String com.dashuai.springboot.controller.AdminController.doLogin(java.lang.String,java.lang.String,javax.servlet.http.HttpServletRequest)
2017-10-28 22:16:13.928  INFO 5840 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/admin/logout.html]}" onto public java.lang.String com.dashuai.springboot.controller.AdminController.logout()
2017-10-28 22:16:13.930  INFO 5840 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2017-10-28 22:16:13.930  INFO 5840 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2017-10-28 22:16:13.961  INFO 5840 --- [  restartedMain] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-10-28 22:16:13.961  INFO 5840 --- [  restartedMain] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-10-28 22:16:13.990  INFO 5840 --- [  restartedMain] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-10-28 22:16:14.393  INFO 5840 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2017-10-28 22:16:14.451  INFO 5840 --- [  restartedMain] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2017-10-28 22:16:14.453  INFO 5840 --- [  restartedMain] o.s.j.e.a.AnnotationMBeanExporter        : Bean with name 'dataSource' has been autodetected for JMX exposure
2017-10-28 22:16:14.457  INFO 5840 --- [  restartedMain] o.s.j.e.a.AnnotationMBeanExporter        : Located MBean 'dataSource': registering with JMX server as MBean [com.alibaba.druid.pool:name=dataSource,type=DruidDataSource]
2017-10-28 22:16:14.493  INFO 5840 --- [  restartedMain] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2017-10-28 22:16:14.497  INFO 5840 --- [  restartedMain] c.d.springboot.SpringbootApplication     : Started SpringbootApplication in 4.362 seconds (JVM running for 4.875)


好了,下面把整个项目重要代码都粘上

<?xml version="1.0" encoding="UTF-8"?>
<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.dashuai</groupId>
<artifactId>springboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>springboot</name>
<description>Demo project for Spring Boot</description>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
<scope>true</scope>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.31</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- 集成ehcache需要的依赖-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
</dependency>

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>

<!--工具包,加密算法 -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.4</version>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
</plugins>

</build>

</project>
package com.dashuai.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@EnableTransactionManagement @EnableCaching @SpringBootApplication public class SpringbootApplication { public static void main(String[] args) { SpringApplication.run(SpringbootApplication.class, args); } }

#log
logging.file=mylog.log
logging.level.root=info
logging.level.org.springframework=info
logging.level.org.hibernate=warn
#logging.level.org.hibernate.engine.QueryParameters=DEBUG
#logging.level.org.hibernate.engine.query.HQLQueryPlan=DEBUG
#logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
#logging.level.org.hibernate.type.descriptor.sql.BasicExtractor=TRACE
#控制是否显示缓存相关日志
logging.level.org.hibernate.cache=DEBUG
#thymeleaf
spring.thymeleaf.cache=false

#mysql
spring.datasource.driver-class-name= com.mysql.jdbc.Driver
spring.datasource.url=jdbc\:mysql\://localhost\:3306/dadmin?useUnicode\=true&characterEncoding\=UTF-8
spring.datasource.username=root
spring.datasource.password=123456

#druid
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.filters=stat
spring.datasource.maxActive= 20
spring.datasource.initialSize= 1
spring.datasource.maxWait= 60000
spring.datasource.minIdle =1
spring.datasource.timeBetweenEvictionRunsMillis= 60000
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery= select 'x'
spring.datasource.testWhileIdle= true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn= false
spring.datasource.poolPreparedStatements=true
spring.datasource.maxOpenPreparedStatements= 20

#hibernate
spring.jpa.database = MYSQL
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto = update
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
spring.jpa.properties.hibernate.format_sql = true
spring.jpa.properties.hibernate.show_sql = true
spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext
# 打开hibernate统计信息
spring.jpa.properties.hibernate.generate_statistics=true
# 打开二级缓存
spring.jpa.properties.hibernate.cache.use_second_level_cache=true
# 打开查询缓存
spring.jpa.properties.hibernate.cache.use_query_cache=true
# 指定缓存provider
spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
# 配置shared-cache-mode
spring.jpa.properties.javax.persistence.sharedCache.mode=ENABLE_SELECTIVE
spring.jpa.properties.hibernate.cache.provider_configuration_file_resource_path=classpath:ehcache.xml
spring.cache.ehcache.config=ehcache.xml
package com.dashuai.springboot.config;

import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DruidConfig {

@Bean
public ServletRegistrationBean druidStatView() {
ServletRegistrationBean registration = new ServletRegistrationBean(new StatViewServlet());
registration.addUrlMappings("/druid/*");
return registration;
}

@Bean
public FilterRegistrationBean druidWebStatFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean(new WebStatFilter());
registration.addInitParameter("exclusions","/css/*,/style/*,/js/*,*.js,*.css,/druid*,/attached/*,*.jsp");
registration.addInitParameter("principalSessionName","sessionUser");
registration.addInitParameter("profileEnable","true");
registration.addUrlPatterns("/*");
registration.setOrder(1);
return registration;
}
}

package com.dashuai.springboot.config;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManagerFactory;

@Configuration
public class SessionFactoryConfig {

@Autowired
private EntityManagerFactory entityManagerFactory;

@Bean(name="SessionFactory")
public SessionFactory getSessionFactory() {
if (entityManagerFactory.unwrap(SessionFactory.class) == null) {
throw new NullPointerException("factory is not a hibernate factory");
}
return entityManagerFactory.unwrap(SessionFactory.class);
}

/**
* 解决异常 org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
* @return
*/
@Bean(name="openSessionInViewFilter")
public FilterRegistrationBean openSessionInViewFilter() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean(new org.springframework.orm.hibernate4.support.OpenSessionInViewFilter());
filterRegistration.addInitParameter("singleSession","true");
filterRegistration.addInitParameter("sessionFactoryBeanName","SessionFactory");
filterRegistration.addUrlPatterns("/*");
return filterRegistration;
}

}
package com.dashuai.springboot.config;

import com.dashuai.springboot.shiro.*;
import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;

import javax.servlet.Filter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

@Bean(name = "systemAuthFilter")
public SystemFormAuthFilter getSystemFormAuthFilter() {
SystemFormAuthFilter formAuthFilter = new SystemFormAuthFilter();
formAuthFilter.setSuccessUrl("/admin/index.html");
formAuthFilter.setLoginUrl("/admin/login.html");
return formAuthFilter;
}

@Bean(name = "normalAuthFilter")
public NormalFormAuthFilter getNormalFormAuthFilter() {
NormalFormAuthFilter formAuthFilter = new NormalFormAuthFilter();
formAuthFilter.setSuccessUrl("/index.html");
formAuthFilter.setLoginUrl("/login.html");
return formAuthFilter;
}

@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean getShiroFilterFactoryBean() {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(getDefaultWebSecurityManager());
Map<String, Filter> filters = new LinkedHashMap<>();
filters.put("authsys", getSystemFormAuthFilter());
filters.put("authnor", getNormalFormAuthFilter());
shiroFilterFactoryBean.setFilters(filters);
LinkedHashMap<String, String> filterChainDefinitionMap=new LinkedHashMap<>();
filterChainDefinitionMap.put("/login.html", "anon");
filterChainDefinitionMap.put("/admin/login.*", "anon");
filterChainDefinitionMap.put("/admin", "authsys");
filterChainDefinitionMap.put("/admin/", "authsys");
filterChainDefinitionMap.put("/admin/**.html", "authsys");// 也就是说 这个配置请细致配置
// filterChainDefinitionMap.put("/admin/**", "authsys");// 不可以加这个,否则/admin/login.*失效
filterChainDefinitionMap.put("/user/**", "authnor");
filterChainDefinitionMap.put("/**", "anon");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}

@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setCacheManager(getMemoryConstrainedCacheManager());
securityManager.setAuthenticator(getDefautModularRealm());
ArrayList<Realm> list = new ArrayList<>();
list.add(getSystemUserRealm());
list.add(getNormalUserRealm());
securityManager.setRealms(list);
securityManager.setSessionManager(getDefaultWebSessionManager());
securityManager.setRememberMeManager(getCookieRememberMeManager());
return securityManager;
}

@Bean(name = "memoryConstrainedCacheManager")
public MemoryConstrainedCacheManager getMemoryConstrainedCacheManager() {
MemoryConstrainedCacheManager manager = new MemoryConstrainedCacheManager();
return manager;
}

@Bean(name = "defineModularRealmAuthenticator")
public DefautModularRealm getDefautModularRealm() {
DefautModularRealm realm = new DefautModularRealm();
Map<String, Object> definedRealms = new HashMap<>();
definedRealms.put("systemAuthorizingRealm", getSystemUserRealm());
definedRealms.put("normalAuthorizingRealm", getNormalUserRealm());
realm.setDefinedRealms(definedRealms);
realm.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
return realm;
}

@Bean(name = "systemUserRealm")
public SystemUserRealm getSystemUserRealm() {
SystemUserRealm realm = new SystemUserRealm();
return realm;
}

@Bean(name = "normalUserRealm")
public NormalUserRealm getNormalUserRealm() {
NormalUserRealm realm = new NormalUserRealm();
return realm;
}

@Bean(name = "sessionManager")
public DefaultWebSessionManager getDefaultWebSessionManager() {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setSessionDAO(getEnterpriseCacheSessionDAO());
sessionManager.setGlobalSessionTimeout(1800000);
sessionManager.setSessionValidationInterval(1800000);
sessionManager.setSessionIdCookieEnabled(true);
sessionManager.setSessionValidationSchedulerEnabled(true);
sessionManager.setSessionIdCookie(getSimpleCookie());
return sessionManager;
}

@Bean(name = "sessionDAO")
public EnterpriseCacheSessionDAO getEnterpriseCacheSessionDAO() {
EnterpriseCacheSessionDAO sessionDAO = new EnterpriseCacheSessionDAO();
sessionDAO.setCacheManager(getEhCacheManager());
return sessionDAO;
}

@Bean(name = "shiroCacheManager")
public EhCacheManager getEhCacheManager() {
EhCacheManager em = new EhCacheManager();
em.setCacheManagerConfigFile("classpath:ehcache.xml");
return em;
}

@Bean(name = "simpleCookie")
public SimpleCookie getSimpleCookie() {
SimpleCookie simpleCookie = new SimpleCookie("shiro.sesssion");
simpleCookie.setPath("/");
return simpleCookie;
}

@Bean(name = "rememberMeManager")
public CookieRememberMeManager getCookieRememberMeManager() {
CookieRememberMeManager meManager = new CookieRememberMeManager();
meManager.setCipherKey(org.apache.shiro.codec.Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));
meManager.setCookie(getRememberMeCookie());
return meManager;
}

@Bean(name = "rememberMeCookie")
public SimpleCookie getRememberMeCookie() {
SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
simpleCookie.setHttpOnly(true);
simpleCookie.setMaxAge(604800); // 7天
return simpleCookie;
}@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));
filterRegistration.addInitParameter("targetFilterLifecycle", "true");
filterRegistration.addUrlPatterns("/*");
return filterRegistration;
}

}

package com.dashuai.springboot.controller;

import com.dashuai.springboot.entity.SystemUser;
import com.dashuai.springboot.shiro.CustomUsernamePasswordToken;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;

@Controller
@RequestMapping("/admin")
public class AdminController {

private final Logger logger = Logger.getLogger(AdminController.class);

@RequestMapping
public String index2(){
return "admin/index";
}

@RequestMapping(value = {"/","/index.html"})
public String index(){
return "admin/index";
}

@RequestMapping("/login.html")
public String loginIndex(){
// 防止重复登陆
Subject subject = SecurityUtils.getSubject();
if(null==subject||null==subject.getPrincipal()||!subject.isAuthenticated()){
return "admin/login";
}
return "redirect:/admin";
}

@RequestMapping("/login.do")
public String doLogin(String username, String password, HttpServletRequest request){
logger.info("进入到 doLogin方法中 ");
if(null==username||username.equals("")){
return "redirect:/admin/login.html";
}
logger.info("登陆请求 username:"+username+",password:"+password);
try {
SecurityUtils.getSubject().login(new CustomUsernamePasswordToken(username,
DigestUtils.md5Hex(password),false,
CustomUsernamePasswordToken.LOGIN_ADMIN_TYPE));

System.err.println("登陆成功,"+SecurityUtils.getSubject().getPrincipal());

logger.info("登陆成功,"+SecurityUtils.getSubject().getPrincipal());
SystemUser systemUser = (SystemUser) SecurityUtils.getSubject().getPrincipal();
request.getSession().setAttribute("SystemUser",systemUser);
logger.info("Session 中存入 登陆信息 key: SystemUser value: "+systemUser);

return "redirect:/admin/index.html";
} catch (IncorrectCredentialsException e) {
logger.info(e.getMessage());
request.setAttribute("msg", "登陆失败,密码错误");
return "admin/login";
} catch (UnknownAccountException e) {
request.setAttribute("msg", "登陆失败,用户名不存在");
logger.info(e.getMessage());
return "admin/login";
}catch (AccountException e) {
request.setAttribute("msg", "您的账号被禁用了!");
logger.info(e.getMessage());
return "admin/login";
}

}

@RequestMapping("/logout.html")
public String logout(){
Subject subject = SecurityUtils.getSubject();
if (null!=subject) {
subject.logout();
}
return "redirect:/admin/login.html";
}

}

package com.dashuai.springboot.dao;

import org.hibernate.Session;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

public interface BaseDao<T> {

public Session getCurrentSession();

public Serializable save(T o);

public void delete(T o);

public void saveOrUpdate(T o);

public void update(T o);

public List<T> getByHQL(boolean withCache, String hql, Map<String, Object> params);

public List<T> getByHQL(boolean withCache, String hql, Map<String, Object> params, int page, int rows);

public long countByHQL(boolean withCache, String hql, Map<String, Object> params);

public long countBySQL(boolean withCache, String sql, Map<String, Object> params);

public List<Map<String,Object>> getResultMapBySql(String sql, Map<String, Object> params);

public List<Map<String,Object>> getResultMapBySql(String sql, Map<String, Object> params, int page, int rows);

public int executeHQL(String hql, Map<String, Object> params);

public int executeSQL(String sql, Map<String, Object> params);

}
package com.dashuai.springboot.dao.impl;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import com.dashuai.springboot.dao.BaseDao;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository("baseDao")
public class BaseDaoImpl<T> implements BaseDao<T> {

@Autowired
private SessionFactory sessionFactory;

public Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}

public Serializable save(T o) {
return getCurrentSession().save(o);
}
public void delete(T o) {
getCurrentSession().delete(o);
}
public void saveOrUpdate(T o) {
getCurrentSession().saveOrUpdate(getCurrentSession().merge(o));
}

public void update(T o) {
getCurrentSession().update(o);
}

public List<T> getByHQL(boolean withCache, String hql, Map<String, Object> params) {
Query q = getCurrentSession().createQuery(hql);
if (params != null && !params.isEmpty()) {
for (String key : params.keySet()) {
q.setParameter(key, params.get(key));
}
}
return q.setCacheable(withCache).list();
}

public List<T> getByHQL(boolean withCache, String hql, Map<String, Object> params, int page, int rows) {
Query q = getCurrentSession().createQuery(hql);
if (params != null && !params.isEmpty()) {
for (String key : params.keySet()) {
q.setParameter(key, params.get(key));
}
}
return q.setCacheable(withCache).setFirstResult((page - 1) * rows)//
.setMaxResults(rows)//
.list();
}

public long countByHQL(boolean withCache, String hql, Map<String, Object> params) {
Query q = getCurrentSession().createQuery(hql);
if (params != null && !params.isEmpty()) {
for (String key : params.keySet()) {
q.setParameter(key, params.get(key));
}
}
return (Long) q.setCacheable(withCache).uniqueResult();
}

public long countBySQL(boolean withCache, String sql, Map<String, Object> params) {
SQLQuery q = getCurrentSession().createSQLQuery(sql);
if (params != null && !params.isEmpty()) {
for (String key : params.keySet()) {
q.setParameter(key, params.get(key));
}
}
return (Long) q.setCacheable(withCache).uniqueResult();
}

public List<Map<String, Object>> getResultMapBySql(String sql, Map<String, Object> params) {
SQLQuery q = getCurrentSession().createSQLQuery(sql);
if (params != null && !params.isEmpty()) {
for (String key : params.keySet()) {
q.setParameter(key, params.get(key));
}
}
return q.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();
}

public List<Map<String, Object>> getResultMapBySql(String sql, Map<String, Object> params, int page, int rows) {
SQLQuery q = getCurrentSession().createSQLQuery(sql);
if (params != null && !params.isEmpty()) {
for (String key : params.keySet()) {
q.setParameter(key, params.get(key));
}
}
return q.setFirstResult((page - 1) * rows)//
.setMaxResults(rows)//
.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP)//
.list();
}

public int executeHQL(String hql,Map<String,Object> params) {
Query q = getCurrentSession().createQuery(hql);
if (params != null && !params.isEmpty()) {
for (String key : params.keySet()) {
q.setParameter(key, params.get(key));
}
}
return q.executeUpdate();
}

public int executeSQL(String sql,Map<String,Object> params) {
SQLQuery q = getCurrentSession().createSQLQuery(sql);
if (params != null && !params.isEmpty()) {
for (String key : params.keySet()) {
q.setParameter(key, params.get(key));
}
}
return q.executeUpdate();
}

}
package com.dashuai.springboot.dao;

import com.dashuai.springboot.entity.SystemUser;

import java.io.Serializable;

public interface SystemUserDao {

Serializable saveSystemUser(SystemUser user);

SystemUser findUserByUsername(String username);

}

package com.dashuai.springboot.dao.impl;

import com.dashuai.springboot.dao.SystemUserDao;
import com.dashuai.springboot.entity.SystemUser;
import org.springframework.stereotype.Repository;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Repository("systemUserDao")
public class SystemUserDaoImpl extends BaseDaoImpl<SystemUser> implements SystemUserDao {

public Serializable saveSystemUser(SystemUser user) {
return save(user);
}

public SystemUser findUserByUsername(String username) {
String hql = "from SystemUser where username=:username";
Map<String,Object> params = new HashMap<>();
params.put("username",username);
List<SystemUser> list = getByHQL(true,hql,params);
if(null!=list&&list.isEmpty()){
return null;
}
return list.get(0);
}

}
package com.dashuai.springboot.entity;

import com.fasterxml.jackson.annotation.JsonFormat;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Cache;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;

/**
*  用户表。(通用用户,能否访问后台,看是否有后台角色)
*/
@Entity
@Table(name="system_user")
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class SystemUser implements Serializable {

@Id
@GenericGenerator(name = "systemUUID", strategy = "uuid")
@GeneratedValue(generator = "systemUUID")
@Column(name = "uuid",updatable = false, nullable = false)
private String uuid;     // 表主键
@Column
private String username; // 登录用户名
@Column
private String password; // 登录密码
@Column
private String isRoot; // 最高权限管理员; "1":root "0": notRoot
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Column
private Date registerDate;
@Column
private Integer status; // 账号状态: 0:正常;1:禁用

public Date getRegisterDate() {
return registerDate;
}

public void setRegisterDate(Date registerDate) {
this.registerDate = registerDate;
}

public Integer getStatus() {
return status;
}

public void setStatus(Integer status) {
this.status = status;
}

public String getUuid() {
return uuid;
}

public void setUuid(String uuid) {
this.uuid = uuid;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public String getIsRoot() {
return isRoot;
}

public void setIsRoot(String isRoot) {
this.isRoot = isRoot;
}

@Override
public String toString() {
return "SystemUser{" +
"uuid='" + uuid + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
", isRoot='" + isRoot + '\'' +
", registerDate=" + registerDate +
", status=" + status +
'}';
}
}
package com.dashuai.springboot.service;

import com.dashuai.springboot.entity.SystemUser;

public interface SystemUserService {

String saveSystemUser(SystemUser user);

SystemUser findUserByUsername(String username);

}


package com.dashuai.springboot.service.impl;

import com.dashuai.springboot.dao.SystemUserDao;
import com.dashuai.springboot.entity.SystemUser;
import com.dashuai.springboot.service.SystemUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("systemUserService")
public class SystemUserServiceImpl implements SystemUserService {

@Autowired
SystemUserDao systemUserDao;

@Transactional
public String saveSystemUser(SystemUser user) {
return (String)systemUserDao.saveSystemUser(user);
}

@Transactional(readOnly = true)
public SystemUser findUserByUsername(String username) {
return systemUserDao.findUserByUsername(username);
}

}


package com.dashuai.springboot.shiro;

import org.apache.shiro.authc.UsernamePasswordToken;

public class CustomUsernamePasswordToken extends UsernamePasswordToken {

public static final int LOGIN_ADMIN_TYPE=1000; // 后台
public static final int LOGIN_FRONT_TYPE=999;  // 前台

private int loginType; // 是否是系统后台用户还是前台用户

public int getLoginType() {
return loginType;
}

public void setLoginType(int loginType) {
this.loginType = loginType;
}

public CustomUsernamePasswordToken (String username, String password, boolean rememberMe, int loginType) {
super(username, password, rememberMe);
this.loginType = loginType;
}

}
package com.dashuai.springboot.shiro;

import org.apache.log4j.Logger;
import org.apache.shiro.ShiroException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.util.CollectionUtils;

import java.util.Collection;
import java.util.Map;

/**
* 管理多个Realms
*/
public class DefautModularRealm extends ModularRealmAuthenticator {

private static final Logger log = Logger.getLogger(DefautModularRealm.class);

private Map<String, Object> definedRealms;

/**
* 多个realm实现
*/
@Override
protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) {
return super.doMultiRealmAuthentication(realms, token);
}

/**
* 调用单个realm执行操作
*/
@Override
protected AuthenticationInfo doSingleRealmAuthentication(Realm realm,AuthenticationToken token) {
log.info("DefautModularRealm doSingleRealmAuthentication Shiro 认证执行的第 3 步 " +token);
// 如果该realms不支持(不能验证)当前token
if (!realm.supports(token)) {
throw new ShiroException("token错误!");
}
AuthenticationInfo info = realm.getAuthenticationInfo(token);
log.info("DefautModularRealm doSingleRealmAuthentication info " +info);
return info;
}

/**
* 判断登录类型执行操作
*/
@Override
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken)throws AuthenticationException {
log.info("DefautModularRealm doAuthenticate Shiro 认证执行的第二步 ");
this.assertRealmsConfigured();
Realm realm = null;
CustomUsernamePasswordToken token = (CustomUsernamePasswordToken) authenticationToken;
//判断是否是后台用户
if (token.getLoginType()==CustomUsernamePasswordToken.LOGIN_ADMIN_TYPE) {
realm = (Realm) this.definedRealms.get("systemAuthorizingRealm");// 查看shiro的配置
}
else if (token.getLoginType()==CustomUsernamePasswordToken.LOGIN_FRONT_TYPE){
realm = (Realm) this.definedRealms.get("normalAuthorizingRealm");
}
log.info("doAuthenticate ==> "+realm);

return this.doSingleRealmAuthentication(realm, authenticationToken);
}
/**
* 判断realm是否为空
*/
@Override
protected void assertRealmsConfigured() throws IllegalStateException {
this.definedRealms = this.getDefinedRealms();
if (CollectionUtils.isEmpty(this.definedRealms)) {
throw new ShiroException("值传递错误!");
}
}

public Map<String, Object> getDefinedRealms() {
return this.definedRealms;
}

public void setDefinedRealms(Map<String, Object> definedRealms) {
this.definedRealms = definedRealms;
}

}
package com.dashuai.springboot.shiro;

import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
* 前台 用户登录的验证
*/
public class NormalFormAuthFilter extends FormAuthenticationFilter {

private static final Logger log = LoggerFactory
.getLogger(SystemFormAuthFilter.class);

@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
log.info("NormalFormAuthFilter onAccessDenied Shiro 前台 认证执行的第一步 ");
return super.onAccessDenied(request, response);
}

}

package com.dashuai.springboot.shiro;

import com.dashuai.springboot.entity.SystemUser;
import com.dashuai.springboot.service.SystemUserService;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
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.springframework.beans.factory.annotation.Autowired;

import java.util.Arrays;

/**
* 这里验证多个 Realm,前后台 分开验证
*/
public class NormalUserRealm extends AuthorizingRealm {

private static final Logger log = Logger
.getLogger(SystemUserRealm.class);

@Autowired
private SystemUserService systemUserService;

/**
* Shiro权限认证,即权限授权
*
* 关于多个Realm授权的问题。对于本项目配置而言是这样的。
* 本项目配置了两个: SystemUserRealm;NormalUserRealm;
*  它会按配置顺序执行。先SystemUserRealm;
*  如果在先SystemUserRealm发现了想要的角色或者权限,那么不执行NormalUserRealm;
*  如果在SystemUserRealm没有找到,那么继续执行NormalUserRealm中授权方法。
*
*/
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
log.info("前台用户 NormalUserRealm Shiro 请求授权");

return null;
}

/**
* 用户认证,登录认证
*/
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
log.info("前台用户 NormalUserRealm 用户认证 Shiro 认证执行的第 4 步 " );
CustomUsernamePasswordToken token = (CustomUsernamePasswordToken) authenticationToken;
String username = token.getUsername();
log.info("NormalUserRealm token username: "+username+", password: "+new String(token.getPassword()));
SystemUser systemUser = systemUserService.findUserByUsername(username);
log.info("NormalUserRealm  systemUser: "+systemUser);
if(null==systemUser){
throw new UnknownAccountException("NormalUserRealm tips: 用户名不存在");
}else if(!systemUser.getPassword().equals(new String(token.getPassword()))){
throw new IncorrectCredentialsException("NormalUserRealm tips: 密码错误,请重试");
}else if(systemUser.getStatus()==1){
throw new AccountException("NormalUserRealm tips: 账号被禁用");
}else{
return new SimpleAuthenticationInfo(systemUser,systemUser.getPassword(),getName());
}
}

}
package com.dashuai.springboot.shiro;

import org.apache.log4j.Logger;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
* 后台的用户登录认证
*/
public class SystemFormAuthFilter extends FormAuthenticationFilter {

private static final Logger log = Logger
.getLogger(SystemFormAuthFilter.class);

@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
log.info("SystemFormAuthFilter onAccessDenied Shiro 认证执行的第一步 ");
return super.onAccessDenied(request, response);
}

/*@Override
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
log.info("SystemFormAuthFilter onLoginSuccess  ");
//我们登录成功之后要跳到一个固定的页面,通常是跳到首页,
WebUtils.getAndClearSavedRequest(request);
WebUtils.redirectToSavedRequest(request,response,"admin/index.html");
return super.onLoginSuccess(token, subject, request, response);
}*/
}
package com.dashuai.springboot.shiro;

import com.dashuai.springboot.entity.SystemUser;
import com.dashuai.springboot.service.SystemUserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

//import org.apache.log4j.Logger;

/**
* 系统用户领域(后台用户操作)
* 在 shiro 中,用户需要提供principals(身份)和credentials(证明)给shiro,从而应用能验证用户身份:
principals:身份,即主体的标识属性,可以是任何东西,如用户名、邮箱等,唯一即可。
一个主体可以有多个principals,但只有一个Primary principals,一般是用户名/密码/手机号。
credentials:证明/凭证,即只有主体知道的安全值,如密码/数字证书等。
最常见的principals和credentials组合就是用户名/密码了。
*/
public class SystemUserRealm extends AuthorizingRealm {

private static final Logger log = LoggerFactory.getLogger(SystemUserRealm.class);

@Autowired
private SystemUserService systemUserService;

/**
* Shiro权限认证,即权限授权
* 会进入授权方法一共有三种情况!
1、subject.hasRole(“admin”) 或 subject.isPermitted(“admin”):自己去调用这个是否有什么角色或者是否有什么权限的时候;
2、@RequiresRoles("admin") :在方法上加注解的时候;
3、[@shiro.hasPermission name = "admin"][/@shiro.hasPermission]:在页面上加shiro标签的时候,即进这个页面的时候扫描到有这个标签的时候。
*/
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
log.info("SystemUserRealm Shiro请求授权 ");
//        SystemUser systemUser = (SystemUser) SecurityUtils.getSubject().getPrincipal();
//        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//        if(systemUser.getIsRoot().equals(ConstantUtil.IS_ROOT)){
//            Collection<String> roles = new ArrayList<>();
//            List<SystemRole> list = systemRoleService.getRootAllRoles();
//            for(SystemRole systemRole:list){
//                roles.add(systemRole.getRoleName());
//            }
//            info.addRoles(roles);
//            log.info("SystemUserRealm Root 获取角色:{} ", Arrays.toString(info.getRoles().toArray()));
//        }else{
//            // 非root用户
//            info.addRoles(systemUserRoleService.getAllRolesNameByUserId(systemUser.getUuid()));
//            log.info("SystemUserRealm 后台 非ROOT 获取角色: {}", Arrays.toString(info.getRoles().toArray()));
//        }
//        return info;
return null;
}

/**
* 用户认证,登录认证
*/
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws UnknownAccountException,IncorrectCredentialsException {
log.info("SystemUserRealm doGetAuthenticationInfo Shiro 认证执行的第 4 步 " );
CustomUsernamePasswordToken token = (CustomUsernamePasswordToken) authenticationToken;
String username = token.getUsername();
log.info("SystemUserRealm token username: {}, password: {}",username,new String(token.getPassword()));
SystemUser systemUser = systemUserService.findUserByUsername(username);
log.info("SystemUserRealm  systemUser: {}",systemUser);
if(null==systemUser){
throw new UnknownAccountException("SystemUserRealm 提示: 用户名不存在");
}else if(!systemUser.getPassword().equals(new String(token.getPassword()))){
throw new IncorrectCredentialsException("SystemUserRealm 提示:密码错误");
}else if(systemUser.getStatus()==1){
throw new AccountException("SystemUserRealm 提示: 账号被禁用");
}else{
return new SimpleAuthenticationInfo(systemUser,systemUser.getPassword(),getName());
}

}

}
<!DOCTYPE html>
<html lang="zh"  xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
登陆成功!
<a href="login.html" th:href="@{/admin/logout.html}">退出</a>
</body>
</html>
<!DOCTYPE html>
<html lang="zh"  xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<form action="index.html" th:action="@{/admin/login.do}" method="post" >
用户名: <input type="text" name="username" /><br/>
密码:<input type="password" name="password" /><br/>
<input type="submit" value="登陆" />
</form>
</body>
</html>
2017-10-28 22:24:18.165  INFO 4224 --- [nio-8080-exec-1] c.d.s.controller.AdminController         : 进入到 doLogin方法中
2017-10-28 22:24:18.184  INFO 4224 --- [nio-8080-exec-2] c.d.s.shiro.SystemFormAuthFilter         : SystemFormAuthFilter onAccessDenied Shiro 认证执行的第一步
2017-10-28 22:24:21.570  INFO 4224 --- [nio-8080-exec-3] c.d.s.controller.AdminController         : 进入到 doLogin方法中
2017-10-28 22:24:21.571  INFO 4224 --- [nio-8080-exec-3] c.d.s.controller.AdminController         : 登陆请求 username:root,password:123456
2017-10-28 22:24:21.574  INFO 4224 --- [nio-8080-exec-3] c.d.springboot.shiro.DefautModularRealm  : DefautModularRealm doAuthenticate Shiro 认证执行的第二步
2017-10-28 22:24:21.575  INFO 4224 --- [nio-8080-exec-3] c.d.springboot.shiro.DefautModularRealm  : doAuthenticate ==> com.dashuai.springboot.shiro.SystemUserRealm@7cf211db
2017-10-28 22:24:21.575  INFO 4224 --- [nio-8080-exec-3] c.d.springboot.shiro.DefautModularRealm  : DefautModularRealm doSingleRealmAuthentication Shiro 认证执行的第 3 步 com.dashuai.springboot.shiro.CustomUsernamePasswordToken - root, rememberMe=false
2017-10-28 22:24:21.575  INFO 4224 --- [nio-8080-exec-3] c.d.springboot.shiro.SystemUserRealm     : SystemUserRealm doGetAuthenticationInfo Shiro 认证执行的第 4 步
2017-10-28 22:24:21.575  INFO 4224 --- [nio-8080-exec-3] c.d.springboot.shiro.SystemUserRealm     : SystemUserRealm token username: root, password: e10adc3949ba59abbe56e057f20f883e
2017-10-28 22:24:21.631 DEBUG 4224 --- [nio-8080-exec-3] o.h.cache.internal.StandardQueryCache    : Checking cached query results in region: org.hibernate.cache.internal.StandardQueryCache
2017-10-28 22:24:21.631 DEBUG 4224 --- [nio-8080-exec-3] o.h.c.e.i.r.EhcacheGeneralDataRegion     : key: sql: select systemuser0_.uuid as uuid1_1_, systemuser0_.is_root as is_root2_1_, systemuser0_.password as password3_1_, systemuser0_.register_date as register4_1_, systemuser0_.status as status5_1_, systemuser0_.username as username6_1_ from system_user systemuser0_ where systemuser0_.username=?; parameters: ; named parameters: {username=root}; transformer: org.hibernate.transform.CacheableResultTransformer@110f2
2017-10-28 22:24:21.631 DEBUG 4224 --- [nio-8080-exec-3] o.h.c.e.i.r.EhcacheGeneralDataRegion     : Element for key sql: select systemuser0_.uuid as uuid1_1_, systemuser0_.is_root as is_root2_1_, systemuser0_.password as password3_1_, systemuser0_.register_date as register4_1_, systemuser0_.status as status5_1_, systemuser0_.username as username6_1_ from system_user systemuser0_ where systemuser0_.username=?; parameters: ; named parameters: {username=root}; transformer: org.hibernate.transform.CacheableResultTransformer@110f2 is null
2017-10-28 22:24:21.631 DEBUG 4224 --- [nio-8080-exec-3] o.h.cache.internal.StandardQueryCache    : Query results were not found in cache
Hibernate:
select
systemuser0_.uuid as uuid1_1_,
systemuser0_.is_root as is_root2_1_,
systemuser0_.password as password3_1_,
systemuser0_.register_date as register4_1_,
systemuser0_.status as status5_1_,
systemuser0_.username as username6_1_
from
system_user systemuser0_
where
systemuser0_.username=?
2017-10-28 22:24:21.658 DEBUG 4224 --- [nio-8080-exec-3] o.h.cache.internal.StandardQueryCache    : Caching query results in region: org.hibernate.cache.internal.StandardQueryCache; timestamp=6181685909749760
2017-10-28 22:24:21.659 DEBUG 4224 --- [nio-8080-exec-3] o.h.c.e.i.r.EhcacheGeneralDataRegion     : key: sql: select systemuser0_.uuid as uuid1_1_, systemuser0_.is_root as is_root2_1_, systemuser0_.password as password3_1_, systemuser0_.register_date as register4_1_, systemuser0_.status as status5_1_, systemuser0_.username as username6_1_ from system_user systemuser0_ where systemuser0_.username=?; parameters: ; named parameters: {username=root}; transformer: org.hibernate.transform.CacheableResultTransformer@110f2 value: [6181685909749760, 402880eb5f48f14d015f48f159300000]
2017-10-28 22:24:21.659  INFO 4224 --- [nio-8080-exec-3] c.d.springboot.shiro.SystemUserRealm     : SystemUserRealm  systemUser: SystemUser{uuid='402880eb5f48f14d015f48f159300000', username='root', password='e10adc3949ba59abbe56e057f20f883e', isRoot='null', registerDate=null, status=0}
2017-10-28 22:24:21.661  INFO 4224 --- [nio-8080-exec-3] c.d.springboot.shiro.DefautModularRealm  : DefautModularRealm doSingleRealmAuthentication info SystemUser{uuid='402880eb5f48f14d015f48f159300000', username='root', password='e10adc3949ba59abbe56e057f20f883e', isRoot='null', registerDate=null, status=0}
登陆成功,SystemUser{uuid='402880eb5f48f14d015f48f159300000', username='root', password='e10adc3949ba59abbe56e057f20f883e', isRoot='null', registerDate=null, status=0}
2017-10-28 22:24:21.664  INFO 4224 --- [nio-8080-exec-3] c.d.s.controller.AdminController         : 登陆成功,SystemUser{uuid='402880eb5f48f14d015f48f159300000', username='root', password='e10adc3949ba59abbe56e057f20f883e', isRoot='null', registerDate=null, status=0}
2017-10-28 22:24:21.666  INFO 4224 --- [nio-8080-exec-3] c.d.s.controller.AdminController         : Session 中存入 登陆信息 key: SystemUser value: SystemUser{uuid='402880eb5f48f14d015f48f159300000', username='root', password='e10adc3949ba59abbe56e057f20f883e', isRoot='null', registerDate=null, status=0}


<ehcache name="springBoot_Ehcache" updateCheck="false">
<diskStore path="../springBoot_Ehcache"/>
<!-- hibernate ehcache-->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
/>
<cache name="org.hibernate.cache.spi.UpdateTimestampsCache"
maxElementsInMemory="5000"
eternal="true"
overflowToDisk="true"/>
<cache name="org.hibernate.cache.internal.StandardQueryCache"
maxElementsInMemory="10000"
eternal="false"
timeToLiveSeconds="120"
overflowToDisk="true"/>

<!-- shiro ehcache--> <!-- 登录记录缓存 锁定10分钟 --> <cache name="passwordRetryCache" maxElementsInMemory="2000" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="0" overflowToDisk="false" statistics="true"> </cache> <cache name="authorizationCache" maxElementsInMemory="2000" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="0" overflowToDisk="false" statistics="true"> </cache> <cache name="authenticationCache" maxElementsInMemory="2000" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="0" overflowToDisk="false" statistics="true"> </cache> <cache name="shiro-activeSessionCache" maxElementsInMemory="2000" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="0" overflowToDisk="false" statistics="true"> </cache> <cache name="shiro_cache" maxElementsInMemory="2000" eternal="false" timeToIdleSeconds="0" timeToLiveSeconds="0" maxElementsOnDisk="0" overflowToDisk="true" memoryStoreEvictionPolicy="FIFO" statistics="true"> </cache>

</ehcache>


好了。应没有遗漏。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: