javascript
SpringMVC4+JPA(Hibernate4)+Spring-data-jpa+Shiro整合
2019獨角獸企業重金招聘Python工程師標準>>>
搭建過程的自我記錄過程,不是教程.
拾起寫寫停停的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/jsonxml=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"><defaultCachemaxElementsInMemory="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;/***?認證回調函數,登錄時調用.*/@Overrideprotected?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;}/***?授權查詢回調函數,?進行鑒權但緩存中無用戶的授權信息時調用.*/@Overrideprotected?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算法與迭代次數.*/@PostConstructpublic?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/>輸出.*/@Overridepublic?String?toString()?{return?loginName;}/***?重載hashCode,只計算loginName;*/@Overridepublic?int?hashCode()?{return?Objects.hashCode(loginName);}/***?重載equals,只計算loginName;*/@Overridepublic?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
轉載于:https://my.oschina.net/itwarcraft/blog/339253
總結
以上是生活随笔為你收集整理的SpringMVC4+JPA(Hibernate4)+Spring-data-jpa+Shiro整合的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: cocos2dx 制作单机麻将(二)
- 下一篇: backbone.js入门