springboot+shiro實現權限管理

springboot框架簡介

Spring的誕生是 Java 企業版(Java Enterprise Edition,JEE,也稱 J2EE)的

輕量級代替品。無需開發重量級的 Enterprise JavaBean(EJB),Spring 爲企業級

Java 開發提供了一種相對簡單的方法,通過依賴注入和麪向切面編程,用簡單的Java 對象(Plain Old Java Object,POJO)實現了 EJB 的功能

Spring Boot 簡化了基於Spring的應用開發,只需要“run”就能創建一個獨立的、生產級別的Spring應用。Spring Boot爲Spring平臺及第三方庫提供開箱即用的設置(提供默認設置),這樣我們就可以簡單的開始。多數Spring Boot應用只需要很少的Spring配置。

Spring Boot 主要目標是:

  1. 爲所有 Spring 的開發提供一個從根本上更快的入門體驗。
  2. 開箱即用,但通過自己設置參數,即可快速擺脫這種方式。
  3. 提供了一些大型項目中常見的非功能性特性,如內嵌服務器、安全、指標,健康檢測、外部化配置等。
  4. 絕對沒有代碼生成,也無需 XML 配置。

Shiro框架簡介

Apache Shiro是一個強大且易用的Java安全框架,執行身份驗證、授權、密碼學和會話管理。使用Shiro的易於理解的API,您可以快速、輕鬆地獲得任何應用程序,從最小的移動應用程序到最大的網絡和企業應用程序。

 

Apache Shiro 體系結構

  1. Authentication 認證 ---- 用戶登錄
  2. Authorization 授權 --- 用戶具有哪些權限
  3. Cryptography 安全數據加密
  4. Session Management 會話管理
  5. Web Integration web系統集成
  6. Interations 集成其它應用,spring、緩存框架

 

任務實施

整個項目的體系結構:

pom.xml配置文件,如下所示:

<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>

	<!-- 繼承Spring Boot的默認父工程 -->
	<!-- Spring Boot 父工程 -->
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.4.RELEASE</version>
	</parent>

	<groupId>com.itheima</groupId>
	<artifactId>springboot-shiro</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<!-- 導入依賴 -->
	<dependencies>
		<!-- 導入web支持:SpringMVC開發支持,Servlet相關的程序 -->
		<!-- web支持,SpringMVC, Servlet支持等 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- 導入thymeleaf依賴 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<!-- shiro與spring整合依賴 -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>1.4.0</version>
		</dependency>

		<!-- 導入mybatis相關的依賴 -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.0.9</version>
		</dependency>
		<!-- mysql -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
		<!-- SpringBoot的Mybatis啓動器 -->
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.1.1</version>
		</dependency>
		<!-- thymel對shiro的擴展座標 -->
		<dependency>
			<groupId>com.github.theborakompanioni</groupId>
			<artifactId>thymeleaf-extras-shiro</artifactId>
			<version>2.0.0</version>
		</dependency>
	</dependencies>


	<!-- 修改參數 -->
	<properties>
		<!-- 修改JDK的編譯版本爲1.8 -->
		<java.version>1.8</java.version>
		<!-- 修改thymeleaf的版本 -->
		<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
		<thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.version>
	</properties>
</project>

springboot啓動類:

package com.itheima;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * SpringBoot啓動類
 * @author lenovo
 *
 */
@SpringBootApplication
@MapperScan("com.itheima.mapper")
public class Application {

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

shiro核心API

Subject: 用戶主體(把操作交給SecurityManager)

SecurityManager:安全管理器(關聯Realm)

Realm:Shiro連接數據的橋樑

shiors配置文件ShiroConfig.java的代碼如下:

package com.itheima.shiro;

import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;

/**
 * Shiro的配置類
 * @author lenovo
 *
 */
@Configuration
public class ShiroConfig {

	/**
	 * 創建ShiroFilterFactoryBean
	 */
	@Bean
	public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		
		//設置安全管理器
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		
		//添加Shiro內置過濾器
		/**
		 * Shiro內置過濾器,可以實現權限相關的攔截器
		 *    常用的過濾器:
		 *       anon: 無需認證(登錄)可以訪問
		 *       authc: 必須認證纔可以訪問
		 *       user: 如果使用rememberMe的功能可以直接訪問
		 *       perms: 該資源必須得到資源權限纔可以訪問
		 *       role: 該資源必須得到角色權限纔可以訪問
		 */
		Map<String,String> filterMap = new LinkedHashMap<String,String>();
		/*filterMap.put("/add", "authc");
		filterMap.put("/update", "authc");*/
		
		filterMap.put("/testThymeleaf", "anon");
		//放行login.html頁面
		filterMap.put("/login", "anon");
		
		//授權過濾器
		//注意:當前授權攔截後,shiro會自動跳轉到未授權頁面
		filterMap.put("/add", "perms[user:add]");
		filterMap.put("/update", "perms[user:update]");
		
		filterMap.put("/*", "authc");
		
		//修改調整的登錄頁面
		shiroFilterFactoryBean.setLoginUrl("/toLogin");
		//設置未授權提示頁面
		shiroFilterFactoryBean.setUnauthorizedUrl("/noAuth");
		
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
		
		
		return shiroFilterFactoryBean;
	}
	
	/**
	 * 創建DefaultWebSecurityManager
	 */
	@Bean(name="securityManager")
	public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		//關聯realm
		securityManager.setRealm(userRealm);
		return securityManager;
	}
	
	/**
	 * 創建Realm
	 */
	@Bean(name="userRealm")
	public UserRealm getRealm(){
		return new UserRealm();
	}
	
	/**
	 * 配置ShiroDialect,用於thymeleaf和shiro標籤配合使用
	 */
	@Bean
	public ShiroDialect getShiroDialect(){
		return new ShiroDialect();
	}
}

自定義Realm,代碼如下:

package com.itheima.shiro;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
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.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

import com.itheima.domain.User;
import com.itheima.service.UserService;

/**
 * 自定義Realm
 * @author lenovo
 *
 */
public class UserRealm extends AuthorizingRealm{

	/**
	 * 執行授權邏輯
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
		System.out.println("執行授權邏輯");
		
		//給資源進行授權
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		
		//添加資源的授權字符串
		//info.addStringPermission("user:add");
		
		//到數據庫查詢當前登錄用戶的授權字符串
		//獲取當前登錄用戶
		Subject subject = SecurityUtils.getSubject();
		User user = (User)subject.getPrincipal();
		User dbUser = userSerivce.findById(user.getId());
		
		info.addStringPermission(dbUser.getPerms());
		
		return info;
	}
	
	@Autowired
	private UserService userSerivce;

	/**
	 * 執行認證邏輯
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
		System.out.println("執行認證邏輯");
		
		//編寫shiro判斷邏輯,判斷用戶名和密碼
		//1.判斷用戶名
		UsernamePasswordToken token = (UsernamePasswordToken)arg0;
		
		User user = userSerivce.findByName(token.getUsername());
		
		if(user==null){
			//用戶名不存在
			return null;//shiro底層會拋出UnKnowAccountException
		}
		
		//2.判斷密碼
		return new SimpleAuthenticationInfo(user,user.getPassword(),"");
	}

}

 

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