idea ssm整合shiro shiro的基本用法
阿新 • • 發佈:2019-02-11
http://www.jianshu.com/p/6786ddf54582
參照此篇文章進行設定,此篇文章介紹了一個基本的shiro進行身份驗證和許可權驗證的方法,實測可用,寫這篇部落格的目的為了複習自己配置shiro的基本流程
首先我們要有一個ssm maven專案,搭建ssm專案參照之前的部落格
1.加入pom.xml
http://mvnrepository.com/ maven倉庫的地址
<dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-ehcache -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.3</version>
</dependency>
2.shiro配置檔案配置
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"
>
<!-- 繼承自AuthorizingRealm的自定義Realm,即指定Shiro驗證使用者登入的類為自定義的ShiroDbRealm.java -->
<bean id="myRealm" class="com.pack.shiro.ShiroManager"/>
<!-- Shiro預設會使用Servlet容器的Session,可通過sessionMode屬性來指定使用Shiro原生Session -->
<!-- 即<property name="sessionMode" value="native"/>,詳細說明見官方文件 -->
<!-- 這裡主要是設定自定義的單Realm應用,若有多個Realm,可使用'realms'屬性代替 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"/>
</bean>
<!-- Shiro主過濾器本身功能十分強大,其強大之處就在於它支援任何基於URL路徑表示式的、自定義的過濾器的執行 -->
<!-- Web應用中,Shiro可控制的Web請求必須經過Shiro主過濾器的攔截,Shiro對基於Spring的Web應用提供了完美的支援 -->
<bean id="shiroFilter" name="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- Shiro的核心安全介面,這個屬性是必須的 -->
<property name="securityManager" ref="securityManager"/>
<!-- 要求登入時的連結(可根據專案的URL進行替換),非必須的屬性,預設會自動尋找Web工程根目錄下的"/login.jsp"頁面 -->
<property name="loginUrl" value="/"/>
<!-- 登入成功後要跳轉的連線(本例中此屬性用不到,因為登入成功後的處理邏輯在LoginController裡硬編碼為main.jsp了) -->
<!-- <property name="successUrl" value="/system/main"/> -->
<!-- 使用者訪問未對其授權的資源時,所顯示的連線 -->
<!-- 若想更明顯的測試此屬性可以修改它的值,如unauthor.jsp,然後用[玄玉]登入後訪問/admin/listUser.jsp就看見瀏覽器會顯示unauthor.jsp -->
<property name="unauthorizedUrl" value="/"/>
<!-- Shiro連線約束配置,即過濾鏈的定義 -->
<!-- 此處可配合我的這篇文章來理解各個過濾連的作用http://blog.csdn.net/jadyer/article/details/12172839 -->
<!-- 下面value值的第一個'/'代表的路徑是相對於HttpServletRequest.getContextPath()的值來的 -->
<!-- anon:它對應的過濾器裡面是空的,什麼都沒做,這裡.do和.jsp後面的*表示引數,比方說login.jsp?main這種 -->
<!-- authc:該過濾器下的頁面必須驗證後才能訪問,它是Shiro內建的一個攔截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter -->
<property name="filterChainDefinitions">
<value>
<!-- anon表示此地址不需要任何許可權即可訪問 -->
/static/**=anon
<!-- perms[user:query]表示訪問此連線需要許可權為user:query的使用者 -->
<!--/user=perms[user:query]-->
<!-- roles[manager]表示訪問此連線需要使用者的角色為manager -->
<!--/user/add=roles[manager]-->
<!--所有的請求(除去配置的靜態資源請求或請求地址為anon的請求)都要通過登入驗證,如果未登入則跳到/login-->
/** = authc
</value>
</property>
</bean>
<!-- 保證實現了Shiro內部lifecycle函式的bean執行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- 開啟Shiro的註解(如@RequiresRoles,@RequiresPermissions),需藉助SpringAOP掃描使用Shiro註解的類,並在必要時進行安全邏輯驗證 -->
<!-- 配置以下兩個bean即可實現此功能 -->
<!-- Enable Shiro Annotations for Spring-configured beans. Only run after the lifecycleBeanProcessor has run -->
<bean class="org.apache.shiro.spring.security.intrceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
</beans>
3.在mybatis配置檔案中進行配置
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
">
<!-- 自動掃描 -->
<context:component-scan base-package="com.pack"><!-- base-package 如果多個,用“,”分隔 -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 引入配置檔案 -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</bean>
<!-- spring和MyBatis完美整合,不需要mybatis的配置對映檔案 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 自動掃描mapping.xml檔案 -->
<property name="mapperLocations" value="classpath:mapping/*.xml"></property>
</bean>
<!-- DAO介面所在包名,Spring會自動查詢其下的類 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.pack.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
<!-- (事務管理)transaction manager, use JtaTransactionManager for global tx -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
<!-- 配置自定義Realm -->
<bean id="myRealm" class="com.pack.shiro.ShiroManager"/>
<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"/>
</bean>
<!-- Shiro過濾器 核心-->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- Shiro的核心安全介面,這個屬性是必須的 -->
<property name="securityManager" ref="securityManager"/>
<!-- 身份認證失敗,則跳轉到登入頁面的配置 -->
<property name="loginUrl" value="/login"/>
<!-- 許可權認證失敗,則跳轉到指定頁面 -->
<property name="unauthorizedUrl" value="/angular.jsp"/>
<!-- Shiro連線約束配置,即過濾鏈的定義 -->
<property name="filterChainDefinitions">
<value>
<!--anon 表示匿名訪問,不需要認證以及授權-->
/loginAdmin=anon
<!--authc表示需要認證 沒有進行身份認證是不能進行訪問的-->
/admin*=authc
/student=roles[teacher]
/teacher=perms["user:create"]
</value>
</property>
</bean>
<!-- 保證實現了Shiro內部lifecycle函式的bean執行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- 開啟Shiro註解 -->
<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>
<!-- remenberMe配置 -->
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg value="rememberMe" />
<property name="httpOnly" value="true" />
<!-- 預設記住7天(單位:秒) -->
<property name="maxAge" value="604800" />
</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>
</beans>
4.web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>Archetype Created Web Application</display-name>
<!-- Spring和mybatis的配置檔案 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mybatis.xml</param-value>
</context-param>
<!-- 編碼過濾器 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- shiro過濾器定義 -->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<!-- 該值預設為false,表示生命週期由SpringApplicationContext管理,設定為true則表示由ServletContainer管理 -->
<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>
<!-- Spring監聽器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 防止Spring記憶體溢位監聽器 -->
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<!-- Spring MVC servlet -->
<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>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<!-- 此處可以可以配置成*.do,對應struts的字尾習慣 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.properties</param-value>
</context-param>
<session-config>
<session-timeout>15</session-timeout>
</session-config>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
</web-app>
5.spring-mvc配置
<?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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
"
>
<!-- Spring MVC所掃描的路徑 -->
<context:component-scan base-package="com.pack" use-default-filters="false"><!-- base-package 如果多個,用“,”分隔 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--避免IE執行AJAX時,返回JSON出現下載檔案 -->
<bean id="mappingJacksonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
<!--<mvc:interceptors>-->
<!--<mvc:interceptor>-->
<!--<mvc:mapping path="/**"/>-->
<!--<mvc:exclude-mapping path="/user/loginsc"/>-->
<!--<mvc:exclude-mapping path="/user/logout"/>-->
<!--<mvc:exclude-mapping path="/styles/**"/>-->
<!--<mvc:exclude-mapping path="/scripts/**"/>-->
<!--<mvc:exclude-mapping path="/images/**"/>-->
<!--<bean id="loginInterceptor" class="com.you.interceptor.LoginInterceptor"/>-->
<!--</mvc:interceptor>-->
<!--</mvc:interceptors>-->
<!-- 定義無Controller的path<->view直接對映 -->
<!--<mvc:view-controller path="/" view-name="redirect:/user/first"/>-->
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value = "text/plain;charset=UTF-8" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!--靜態資源對映-->
<mvc:resources mapping="/static/**" location="/static/" />
<!-- 啟動SpringMVC的註解功能,完成請求和註解POJO的對映 -->
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="mappingJacksonHttpMessageConverter" /> <!-- JSON轉換器 -->
</list>
</property>
</bean>
<!-- 定義跳轉的檔案的前後綴 ,檢視模式配置-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 這裡的配置我的理解是自動給後面action的方法return的字串加上字首和字尾,變成一個 可用的url地址 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- 配置檔案上傳,如果沒有使用檔案上傳可以不用配置,當然如果不配,那麼配置檔案中也不必引入上傳元件包 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 預設編碼 -->
<property name="defaultEncoding" value="utf-8" />
<!-- 檔案大小最大值 -->
<property name="maxUploadSize" value="10485760000" />
<!-- 記憶體中的最大值 -->
<property name="maxInMemorySize" value="40960" />
</bean>
<!--此配置一定要在spingmvc的配置檔案中進行配置-->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
<property name="proxyTargetClass" value="true" />
</bean>
<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>
</beans>
6.建立登入頁面
這裡使用了bootstrap以及一個生成svg影象的外掛trianglify,以及彈出框的layer
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8" import="java.util.*"%>
<%@ include file="/WEB-INF/include/taglib.jsp"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<base href="<%=request.getContextPath()%>/" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>登入</title>
<%@ include file="/WEB-INF/include/header.jsp"%>
<style></style>
</head>
<body>
<div class="container">
<form role="form" class="col-md-4 center-block" style="margin:120px auto 0 auto;float:none">
<div class="form-group">
<label for="name">使用者名稱</label>
<input type="text" class="form-control" id="name" placeholder="Enter userName" style="padding:20px;">
</div>
<div class="form-group">
<label for="password">密碼</label>
<input type="password" class="form-control" id="password" placeholder="Password" style="padding:20px;">
</div>
<div class="checkbox">
<label>
<input type="checkbox" id="che"> 記住密碼
</label>
</div>
<div class="col-md-12" style="padding:0px;">
<button type="button" class="btn btn-default btn-block" id="sub" style="padding:10px;">Sign in</button>
</div>
<div id="wordsShow" style="padding-top:20px;text-align: center;"> </div>
</form>
</div>
</body>
<script type="text/javascript">
var h = window.innerHeight, w = window.innerWidth;
// set up the base pattern
var pattern = Trianglify({
height: h,
width: w,
cell_size: 30 + Math.random() * 50});
// png
var png = document.createElement('img');
$("body")[0].background=pattern.png();
$("#sub").click(function(){
var name = $("#name").val();
var password = $("#password").val();
$.get("/user/login",{name:name,password:password},function (text) {
if(text==="2"){
layer.alert('使用者名稱或密碼錯誤', {
skin: 'layui-layer-lan'
,closeBtn: 0
,anim: 4 //動畫型別
});
}else{
window.location.href="/user/tree";
}
});
})
var msgArr = ["有事做有所期待,日子就是幸福的。",
"生活如此難,要怎麼過?一笑而過。",
"碧波盪漾一抹香,茶不醉人人自醉。",
"只要把心放寬,快樂其實很簡單。",
"生活不能等待別人來安排,要自己去爭取與奮鬥!",
"每天都應該是有收穫的,哪怕只是一句話。",
"只要路是對的,就不怕路遠。",
"開心了就笑,不開心就過會再笑。",
"生活的小處,總是藏有大觀。",
"總有一種期待,是家的味道。",
"學會在浮躁中思考,你才知道在喧囂中走向哪裡。",
"萬家燈火中,總有一盞為你點亮。",
"有時候、寧願像個孩子,不肯看太多的事,聽太多的不是,單純的過一輩子多好!",
"用心每一天,不忘初心,方能走遠。",
"即使沒有翅膀,心也要飛翔。",
"積一時之跬步,臻千里之遙程。",
"不開心時,記得要讓心情轉個彎。",
"偷偷擠進的一縷斜陽,送來滿滿的幸福。",
"只要堅持,事情再小也擋不住巨集大的夢。",
"優等的心,不必華麗,但必須堅固。",
"天再高,踮起腳尖就能更接近陽光!",
"與未知的相遇,七分歡喜三分孤寂。",
"有事做有所期待,日子就是幸福的。",
"天時人事日相催,冬至陽生春又來",
"一串淡然的心情,一份純粹的快樂。",
"我不要做普通人。"
];
var index = parseInt(Math.random() * (msgArr.length - 1));
var currentMsg = msgArr[index];
$("#wordsShow").html(currentMsg);
</script>
</html>
7.資料庫結構,使用者表,許可權表,角色表
CREATE TABLE `user` (
`id` VARCHAR(64) NOT NULL PRIMARY KEY,
`name` VARCHAR(20) DEFAULT NULL,
`password` VARCHAR(20) DEFAULT NULL,
`role_Id` INT(11) DEFAULT NULL,
`CREATE_BY` VARCHAR(64) DEFAULT NULL,
`CREATE_DATE` DATETIME(6) DEFAULT NULL,
`UPDATE_BY` VARCHAR(64) DEFAULT NULL,
`UPDATE_DATE` DATETIME(6) DEFAULT NULL,
`REMARKS` VARCHAR(255) DEFAULT NULL,
`DEL_FLAG` CHAR(1) NOT NULL,
KEY `id` (`id`)
) ENGINE=INNODB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
CREATE TABLE `permission` (
id int(11) NOT NULL AUTO_INCREMENT,
`permission_name` varchar(50) DEFAULT NULL,
`roleId` int(11) DEFAULT NULL,
`CREATE_BY` VARCHAR(64) DEFAULT NULL