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

SpringMVC4+JPA(Hibernate4)+Spring-data-jpa+Shiro整合

2014-10-31 15:01 525 查看
搭建过程的自我记录过程,不是教程.

拾起写写停停的ERP系统,打算再次重头开始,要全部采用最新的框架来搭建,基于JDK8:

1. MVC采用SpringMVC4

2. ORM采用JPA(Hibernate实现)采用Hibernate-entitny4,搭配的使用Spring-data-jpa(1.7)

3. View还是用JSP

4. 权限当然是Shiro

5. 日志使用Logback

6. 项目基于Gradle构建

表示自己的代码是挺烂的啊,整个项目整理好了,有信心,再开源.工作之余写的东西,进展缓慢.

那么正式开始搭建项目

一. 环境(先简单写,再完善)

JDK8,包括配置环境变量(这个还需要说?)

Maven,类库的依赖管理,最终还是需要使用maven,从maven.apache.org上下载最新程序,并配置好环境变量

Gradle,从http://www.grale.org下载最新程序,并配置环境变量,配置好后就可以在命令行窗口中使用gradle命令了(配置方式无非是在环境变量中新建GRADLE_HOME,指向下载并解压出来的gradle目录,再将%GRADLE_HOME%\bin添加到path中)

eclipse,我使用的是sts(从spring.io下载),并添加了gradle插件(直接从market中安装就可以了),

二. 建立工程

可以直接使用eclipse的新建工程中,找到gradle的项目,使用simplejava类的工程

编辑build.gradle,完整内容如下,配置完后,需要在build.gradle文件上右键,使用gradle菜单中的刷新命令,下载依赖文件
apply plugin: 'maven'
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin : 'war'
apply plugin: 'jetty'

sourceCompatibility = 1.8
version = '1.0'
jar {
manifest {
attributes 'Implementation-Title': 'lite-erp', 'Implementation-Version': version
}
}

repositories {
mavenCentral()
}

configurations{
//移除依赖
all*.exclude group:'commons-logging'
}

dependencies {
compile (

//spring
'org.springframework:spring-webmvc:4.1.1.RELEASE',
'org.springframework:spring-jdbc:4.1.1.RELEASE',
'org.springframework:spring-orm:4.1.1.RELEASE',
'org.springframework:spring-context-support:4.1.1.RELEASE',

//orm
'org.hibernate:hibernate-entitymanager:4.3.6.Final',
'org.hibernate:hibernate-validator:5.1.2.Final',
'org.springframework.data:spring-data-jpa:1.7.0.RELEASE',
'org.hibernate:hibernate-ehcache:4.3.6.Final',

'mysql:mysql-connector-java:5.1.33',
'com.alibaba:druid:1.0.9',

//shiro
'org.apache.shiro:shiro-spring:1.2.3',
'org.apache.shiro:shiro-ehcache:1.2.3',
'org.apache.shiro:shiro-web:1.2.3',
'org.bouncycastle:bcprov-jdk16:1.46',

//j2ee
'javax.servlet:javax.servlet-api:3.1.0',
'javax.servlet:jstl:1.2',
'javax.servlet.jsp:jsp-api:2.2',

//log
'ch.qos.logback:logback-classic:1.1.2',
'org.slf4j:jul-to-slf4j:1.7.7',

//commons
'net.sf.dozer:dozer:5.5.1',
'commons-codec:commons-codec:1.9',
'commons-io:commons-io:2.4',
'com.google.guava:guava:18.0',
'com.thoughtworks.xstream:xstream:1.4.7',
'org.freemarker:freemarker:2.3.21',
'joda-time:joda-time:2.5',
'com.fasterxml.jackson.core:jackson-databind:2.4.3',
'com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.4.3'

)

compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
testCompile group: 'junit', name: 'junit', version: '4.+'
testCompile 'org.springframework:spring-test:4.1.1.RELEASE'
}test {
systemProperties 'property': 'value'
}

tasks.withType(Compile) {
options.encoding = "UTF-8"
}


添加springside4的源码(省事,并且可以修改内容,直接引用源码,直接从github.com上下载吧)

按maven web的项目结构,创建webapp目录

添加web.xml文件,内容基本来源于springside4中的showcase项目,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>lite-erp</display-name>

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:spring-core.xml,
classpath:spring-shiro.xml
</param-value>
</context-param>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<filter>
<filter-name>openEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

<session-config>
<session-timeout>20</session-timeout>
</session-config>

<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/WEB-INF/views/error/500.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/WEB-INF/views/error/500.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/views/error/404.jsp</location>
</error-page>
</web-app>


添加spring-core.xml,在src/main/resources目录下(其中,从网上找了下加密properties的文件,将数据库密码做了加密处理,暂时可以先去掉,也可以从网上找一下)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-4.1.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd" default-lazy-init="true">

<description>Spring公共配置 </description>
<!-- 加密时候使用 -->
<bean id="propertyConfig" class="lite.erp.ext.spring.PropertyPlaceholderConfigurerExt">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>

<!-- 使用annotation 自动注册bean, 并保证@Required、@Autowired的属性被注入 -->
<context:component-scan base-package="lite">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="url"
value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="filters" value="stat" />
<property name="maxActive" value="20" />
<property name="initialSize" value="2" />
<property name="maxWait" value="30" />
<property name="minIdle" value="4" />
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="validationQuery" value="SELECT 'x'" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<property name="maxOpenPreparedStatements" value="20" />
<property name="removeAbandoned" value="true" /> <!-- 打开removeAbandoned功能 -->
<property name="removeAbandonedTimeout" value="1800" /> <!-- 1800秒,也就是30分钟 -->
<property name="logAbandoned" value="true" /> <!-- 关闭abanded连接时输出错误日志 -->
</bean>

<!-- Jpa Entity Manager 配置 -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter"/>
<property name="packagesToScan" value="lite"/>
<property name="jpaProperties">
<props>
<!-- 命名规则 My_NAME->MyName -->
<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.query.substitutions">true 1, false 0</prop>
<prop key="hibernate.default_batch_fetch_size">16</prop>
<prop key="hibernate.max_fetch_depth">2</prop>
<prop key="hibernate.generate_statistics">true</prop>
<prop key="hibernate.bytecode.use_reflection_optimizer">true</prop>
<!-- <prop key="hibernate.current_session_context_class">thread</prop> -->
<!-- <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop> -->
<prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</prop>
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
<prop key="cache.cache.use_query_cache">true</prop>
<prop key="cache.cache.use_second_level_cache">true</prop>
</props>
</property>
</bean>
<bean id="hibernateJpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform">
<bean factory-method="getDialect" class="org.springside.modules.persistence.Hibernates">
<constructor-arg ref="dataSource"/>
</bean>
</property>
</bean>

<!-- Spring Data Jpa配置 -->
<jpa:repositories base-package="lite"  transaction-manager-ref="transactionManager" entity-manager-factory-ref="entityManagerFactory"/>

<!-- Jpa 事务配置 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

<!-- 使用annotation定义事务 -->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />

<!-- JSR303 Validator定义 -->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />

</beans>


添加spring-mvc.xml,主要支持jsp json两种输出格式,文件存放在src/main/resources目录下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:repository="http://www.springframework.org/schema/data/repository"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd http://www.springframework.org/schema/data/repository http://www.springframework.org/schema/data/repository/spring-repository-1.7.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd" default-lazy-init="true">

<!-- 自动扫描且只扫描@Controller -->
<context:component-scan base-package="lite"
use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
<context:include-filter type="annotation"
expression="org.springframework.web.bind.annotation.ControllerAdvice" />
</context:component-scan>

<mvc:resources location="/assets/" mapping="/assets/*/**" />

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
<mvc:message-converters register-defaults="true">
<!-- 将StringHttpMessageConverter的默认编码设为UTF-8 -->
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8" />
</bean>
<!-- 将Jackson2HttpMessageConverter的默认格式化输出设为true -->
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="prettyPrint" value="true"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>

<!-- REST中根据URL后缀自动判定Content-Type及相应的View -->
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="ignoreAcceptHeader" value="true" />
<property name="defaultContentType" value="application/json" />
<property name="mediaTypes" >
<value>
json=application/json
xml=application/xml
</value>
</property>
</bean>
<!-- 定义JSP文件的位置 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 容器默认的DefaultServletHandler处理 所有静态内容与无RequestMapping处理的URL-->
<mvc:default-servlet-handler/>
<!-- 定义无需Controller的url<->view直接映射 -->
<mvc:view-controller path="/" view-name="index"/>
<!-- 将Controller抛出的异常转到特定View, 保持SiteMesh的装饰效果 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="org.apache.shiro.authz.UnauthorizedException">error/403</prop>
<prop key="java.lang.Throwable">error/500</prop>
</props>
</property>
</bean>

<!-- 支持 Shiro对Controller的方法级AOP安全控制  begin-->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
<property name="proxyTargetClass" value="true" />
</bean>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
<!-- end -->
</beans>


添加spring-shiro.xml,文件位于src/main/resources目录下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:repository="http://www.springframework.org/schema/data/repository"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd http://www.springframework.org/schema/data/repository http://www.springframework.org/schema/data/repository/spring-repository-1.7.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd" default-lazy-init="true">

<description>Shiro安全配置</description>

<!-- Shiro's main business-tier object for web-enabled applications -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="shiroDbRealm" />
<property name="cacheManager" ref="shiroEhcacheManager" />
</bean>

<!-- 項目自定义的Realm, 所有accountService依赖的dao都需要用depends-on声明 -->
<bean id="shiroDbRealm" class="lite.erp.security.shiro.ShiroDbRealm">
<property name="userService" ref="userService"/>
</bean>
<!-- Shiro Filter -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login" />
<property name="successUrl" value="/index" />
<property name="filterChainDefinitions">
<value>
/login = authc
/logout = logout
/assets/** = anon
/register/** = anon
/api/keypair = anon
/admin/** = roles[admin]
/** = user
</value>
</property>
</bean>
<!-- 用户授权信息Cache, 采用EhCache -->
<bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:ehcache/ehcache-shiro.xml"/>
</bean>
<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
</beans>


ehcache配置,包含ehcache.xml与ehcache/ehcache-shiro.xml,按目录结构存放在src/main/resources中
ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<diskStore path="java.io.tmpdir" />
<!--缓存可以存储的总记录量 -->
<!--缓存是否永远不销毁 -->
<!--当缓存中的数据达到最大值时,是否把缓存数据写入磁盘 -->
<!--当缓存闲置时间超过该值,则缓存自动销毁 -->
<!--缓存创建之后,到达该缓存自动销毁 -->
<defaultCache maxElementsInMemory="5"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="15"
timeToLiveSeconds="120"
/>
</ehcache>
src/main/resources/ehcache目录下有ehcache-shiro.xml文件
<ehcache updateCheck="false" name="shiroCache">

<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
/>
</ehcache>


logback配置logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<appender name="rollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>d:/logs/quickstart.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>d:/logs/quickstart.%d{yyyy-MM-dd}.log</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<!-- project default level -->
<logger name="lite" level="INFO" />
<!-- 下面配置一些第三方包的日志过滤级别,用于避免刷屏 -->

<logger name="org.hibernate" level="INFO" />
<logger name="org.springframework" level="INFO" />
<logger name="com.opensymphony" level="INFO" />
<logger name="org.apache" level="INFO" />

<!-- show parameters for hibernate sql 专为 Hibernate 定制 -->
<logger name="org.hibernate.type" level="TRACE" />
<logger name="org.hibernate.type.descriptor.sql.BasicBinder"
level="TRACE" />
<logger name="org.hibernate.type.descriptor.sql.BasicExtractor"
level="DEBUG" />
<logger name="org.hibernate.SQL" level="DEBUG" />
<logger name="org.hibernate.engine.QueryParameters" level="DEBUG" />
<logger name="org.hibernate.engine.query.HQLQueryPlan" level="DEBUG" />

<!--log4jdbc -->
<logger name="jdbc.sqltiming" level="INFO"/>

<root level="WARN">
<appender-ref ref="console" />
<appender-ref ref="rollingFile" />
</root>
</configuration>


shirodbrealm代码
package lite.erp.security.shiro;

import java.io.Serializable;
import java.math.BigInteger;
import java.net.URLDecoder;
import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;

import javax.annotation.PostConstruct;

import lite.erp.security.consts.RbacConsts;
import lite.erp.security.crypto.RSAUtil;
import lite.erp.security.entity.User;
import lite.erp.security.service.IUserService;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
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.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springside.modules.utils.Encodes;

import com.google.common.base.Objects;

public class ShiroDbRealm extends AuthorizingRealm {

private Logger logger = LoggerFactory.getLogger(ShiroDbRealm.class);

protected IUserService userService;

/**
* 认证回调函数,登录时调用.
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
try {
String pwd = decryptPwd(token.getPassword());
token.setPassword(pwd.toCharArray());
} catch (Exception e) {
throw new AccountException("解密密码失败");
}
User user = userService.findUserByName(token.getUsername());
SecurityUtils.getSubject().getSession().removeAttribute("errmsg");
if (user == null) {
SecurityUtils.getSubject().getSession().setAttribute("errmsg", "未找到用户!");
throw new UnknownAccountException();// 没有找到账号
}

if (Boolean.TRUE.equals(user.isLocked())) {
SecurityUtils.getSubject().getSession().setAttribute("errmsg", "账号锁定!");
throw new LockedAccountException(); // 帐号锁定
}
byte[] salt = Encodes.decodeHex(user.getSalt());
ShiroUser shiroUser = new ShiroUser(user.getId(), user.getName(), user.getName());
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(shiroUser,
user.getPassword(), ByteSource.Util.bytes(salt), getName());
SecurityUtils.getSubject().getSession().setAttribute(RbacConsts.CURRENT_USER_SESSION_NAME, user);
return info;
}

private String decryptPwd(char[] pwds) throws Exception{
String pwd1 = new String(pwds);
String pwd = null;
KeyPair key = (KeyPair)SecurityUtils.getSubject().getSession().getAttribute("key");
RSAPrivateKey rsap = (RSAPrivateKey) key.getPrivate();
byte[] en_result = new BigInteger(pwd1, 16).toByteArray();
byte[] bs = RSAUtil.decrypt(rsap,en_result);
String de_orig = new String(bs);
StringBuffer sb = new StringBuffer();
sb.append(de_orig);
String uri_orig = sb.reverse().toString().trim();
//接收的数据做过编码处理,所以要还原
pwd =URLDecoder.decode(uri_orig,"UTF-8");//
return pwd;
}

/**
* 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal();
User user = userService.findUserByName(shiroUser.loginName);
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addRoles(user.getRolesName());
//info.setRoles(this.getUserService().findRolesByUsername(username));
//		info.setStringPermissions(this.getUserService().findPermissionsByUsername(username));

return info;
}

/**
* 设定Password校验的Hash算法与迭代次数.
*/
@PostConstruct
public void initCredentialsMatcher() {
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(IUserService.HASH_ALGORITHM);
matcher.setHashIterations(IUserService.HASH_INTERATIONS);

setCredentialsMatcher(matcher);
}

public IUserService getUserService() {
return userService;
}

public void setUserService(IUserService userService) {
this.userService = userService;
}

/**
* 自定义Authentication对象,使得Subject除了携带用户的登录名外还可以携带更多信息.
*/
public static class ShiroUser implements Serializable {
private static final long serialVersionUID = -1373760761780840081L;
public Long id;
public String loginName;
public String name;

public ShiroUser(Long id, String loginName, String name) {
this.id = id;
this.loginName = loginName;
this.name = name;
}

public String getName() {
return name;
}

/**
* 本函数输出将作为默认的<shiro:principal/>输出.
*/
@Override
public String toString() {
return loginName;
}

/**
* 重载hashCode,只计算loginName;
*/
@Override
public int hashCode() {
return Objects.hashCode(loginName);
}

/**
* 重载equals,只计算loginName;
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
ShiroUser other = (ShiroUser) obj;
if (loginName == null) {
if (other.loginName != null) {
return false;
}
} else if (!loginName.equals(other.loginName)) {
return false;
}
return true;
}
}
}


登陆时采用了rsa对密码进行了加密,从后台解密,源码来源于网络,我测试正常,代码见github.com/itwarcraft/rsa-demo
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: