shiro學習(5)-ssm整合-認證

搭建好SSM項目

項目中引入相關依賴

<dependencies>
    
    <dependency>
	 <groupId>org.springframework</groupId>
	 <artifactId>spring-webmvc</artifactId>
	 <version>5.1.9.RELEASE</version>
    </dependency>
    
    <!-- 添加mysql驅動 -->
 
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.40</version>
    </dependency>
   <dependency>
	    <groupId>com.mchange</groupId>
	    <artifactId>c3p0</artifactId>
	    <version>0.9.5.1</version>
	</dependency>
    <!-- 添加junit用於實現單元測試 -->
    <dependency>
     <groupId>junit</groupId>
     <artifactId>junit</artifactId>
     <version>4.12</version>
     <scope>test</scope>
    </dependency>
    
    <!-- 添加mybatis依賴 -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>2.0.2</version>
    </dependency>

	<dependency>
		<groupId>org.mybatis</groupId>
		<artifactId>mybatis</artifactId>
		<version>3.5.2</version>
	</dependency>

   <!-- 整合mybatis時需要添加如下兩個jar文件-->
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-tx</artifactId>
		<version>5.1.9.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-jdbc</artifactId>
		<version>5.1.9.RELEASE</version>
	</dependency>
	
	<!--整合log4j2,目的是便於我們根據日誌的輸出調試代碼
	  一般添加完依賴會在類路徑添加一個log4j2.xml文件
	 -->
	
   <dependency>
     <groupId>org.apache.logging.log4j</groupId>
     <artifactId>log4j-core</artifactId>
     <version>2.7</version>
   </dependency>
   
   <!-- 整合jackson (在本項目中對請求的響應我們要採用json格式) -->
   
   <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.9.3</version>
   </dependency>
   
  <!--添加JSTL標籤庫的支持 -->
   <dependency>
    <groupId>jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
   </dependency>
   
  <!-- 整合文件上傳功能 -->
   <dependency>
     <groupId>commons-fileupload</groupId>
     <artifactId>commons-fileupload</artifactId>
     <version>1.4</version>
   </dependency>
   
  <!-- 整合shiro 安全框架 -->
  <dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.3.2</version>
  </dependency>
   <dependency>
	    <groupId>com.github.pagehelper</groupId>
	    <artifactId>pagehelper</artifactId>
	    <version>5.1.10</version>
	</dependency>

web.xml文件中註冊shiro過濾器 

<?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_2_5.xsd" version="2.5">
  <display-name>tzms</display-name>
  <filter>
  	<filter-name>CharacterEncoding</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>forceRequestEncoding</param-name>
  		<param-value>true</param-value>
  	</init-param>
  	<init-param>
  		<param-name>forceResponseEncoding</param-name>
  		<param-value>true</param-value>
  	</init-param>
  </filter>
  <filter-mapping>
  	<filter-name>CharacterEncoding</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring-*.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <!-- shiro配置過濾器 DelegatingFilterProxy通過代理模式將spring容器中的bean和filter關聯起來  -->
  <filter>
  	<filter-name>delegatingFilter</filter-name>
  	<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  	<!-- 設置spring容器filter的bean id,如果不設置則找與filter-name一致的bean -->
  		<init-param>
  			<param-name>targetBeanName</param-name>
  			<param-value>shiro</param-value>
  		</init-param>
  </filter>
  <filter-mapping>
  	<filter-name>delegatingFilter</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

添加shiro的配置文件

  注意shiro的配置可以添加在spring的配置文件中。但是爲了便於管理我們再單獨創建一個shiro的配置文件,裏面的Schema還是spring的。

同時web.xml文件中加載spring的位置也需要調整 

 spring-shiro.xml中的內容

<?xml version="1.0" encoding="UTF-8"?>
<beans default-lazy-init="true" 
	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/mvc 
	http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
	http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
	http://www.springframework.org/schema/context 
	http://www.springframework.org/schema/context/spring-context-4.3.xsd">
	
	<!-- 配置web.xml中過濾器對應的spring容器的bean -->
	<bean id="shiro" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean" >
		<!-- 註冊SecurityManager  -->
		<property name="securityManager" ref="securityManager"></property>
		<!-- 登錄時訪問的鏈接 -->
		<property name="loginUrl" value="/loginUI"></property>
		<!-- 用戶無權限時需要訪問的頁面 -->
		<property name="unauthorizedUrl" value="/errorUI"></property>
		<!-- 設置 過濾器鏈 -->
		<property name="filterChainDefinitions">
			<value>
				/bootstrap/** = anon
				/dist/** = anon
				/images/** = anon
				/jquery/** = anon
				/tzms/** = anon
				<!-- 所有請求匿名訪問  /** = anon -->
				<!-- 點擊登錄 不需要認證 -->
				/login = anon
				<!-- 退出 此方法會清空shiro中session的數據 -->
				/logout = logout
				<!-- 所有的url都必須要認證通過後纔可以訪問 -->
				/** = authc
			</value>
		</property>
	</bean>
	
	<!-- 配置安全管理器對象 -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="realm" ref="shiroUserRealm"></property>
	</bean>
	
	<!-- 配置自定義Realm -->
	<bean id="shiroUserRealm" class="com.tanzhou.tzms.common.service.impl.ShiroRealmsOne">
		<!-- 配置憑證匹配器 -->
		<property name="credentialsMatcher" ref="credentialsMatcher"></property>
	</bean>
	
	<!-- 定義憑證匹配器 -->
	<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
		<!-- 匹配散列算法 -->
		<property name="hashAlgorithmName" value="MD5"></property>
		<!-- 匹配散列次數 -->
		<property name="hashIterations" value="1"></property>
	</bean>
	
</beans>

 常見shiro過濾器

過濾器名稱 過濾器類 說明
anon org.apache.shiro.web.filter.authc.AnonymousFilter 匿名過濾器
authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter 如果繼續操作,需要做對應的表單驗證否則不能通過
authcBasic org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter 基本http驗證過濾,如果不通過,跳轉屋登錄頁面
logout org.apache.shiro.web.filter.authc.LogoutFilter 登錄退出過濾器
noSessionCreation org.apache.shiro.web.filter.session.NoSessionCreationFilter 沒有session創建過濾器
perms   org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter 權限過濾器
port org.apache.shiro.web.filter.authz.PortFilter

端口過濾器,可以設置是否是指定端口如果不是跳轉到登錄頁面

rest org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter

http方法過濾器,可以指定如post不能進行訪問等

roles org.apache.shiro.web.filter.authz.RolesAuthorizationFilter

角色過濾器,判斷當前用戶是否指定角色

ssl org.apache.shiro.web.filter.authz.SslFilter

請求需要通過ssl,如果不是跳轉回登錄頁

user org.apache.shiro.web.filter.authc.UserFilter 如果訪問一個已知用戶,比如記住我功能,走這個過濾器

創建Realm接口和實現類 

完成realm的認證功能 

SysShiroServiceImpl類內容

public class SysShiroServiceImpl  implements SysShiroService {
	@Override
	public void login(String username, String password) {
		Subject subject = SecurityUtils.getSubject();
		if(subject.isAuthenticated())return;
		// 把用戶名和密碼封裝爲 UsernamePasswordToken 對象
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        try{//登錄認證 - 調用userRealm
        	subject.login(token);
        }catch (IncorrectCredentialsException ice) {
        	throw new ServiceException("密碼錯誤!");
        } catch(AuthenticationException ae){
        	ae.printStackTrace();
        	throw new ServiceException("認證失敗");
        }
	}
}

自定義Realm認證 

@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		String username =(String)token.getPrincipal();
		//通過用戶名從數據庫中查詢到數據返回對象
		SysUser userInfo = userDao.findObjectByName(username);
		//從對象中得到加密後的密碼
		String password = userInfo.getPassword();
		//從對象中獲取到鹽值
		String salt = userInfo.getSalt();
		//將鹽值專爲十六進制
		ByteSource saltSource = ByteSource.Util.bytes(salt);
		//通過用戶ID從數據庫中查詢到首頁左側導航欄要顯示的菜單
		List<Map<String, Object>> map = sysService.findUserMenus(userInfo.getId());
		//創建CurrentUser類  將查詢得到的用戶id、用戶名稱和用戶需要顯示的菜單放到創建好的對象中
		CurrentUser user = new CurrentUser();
		user.setUserid(userInfo.getId());
		user.setUsername(userInfo.getUsername());
		user.setMenus(map);
		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,password,saltSource,this.getName());
		return info;
	}

完成controller

@RequestMapping("/login")
	@ResponseBody
	public JsonResult login(HttpSession session,String username,String password){
		System.out.println(username+"/"+password);
		loginService.login(username, password);
		Subject subject = SecurityUtils.getSubject();
		System.out.println("是否認證成功:"+subject.isAuthenticated());
		return new JsonResult();
	}

結果爲

密碼錯誤

密碼正確

執行原理流程

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章