Springboot+thymeleaf+shiro整合


Springboot+thymeleaf+shiro

一、簡介

1、Spring Boot

首先,spring的誕生是Java企業版(Java Enterprise Edition,JEE或J2EE)的輕量級替代品。無需開發重量級的EJB(Enterprise JavaBean),spring為企業級Java開發提供了一種相對簡單的方法,通過依賴注入IOC和面向前面編程AOP,用簡單的Java對象(POJO,Plain Old Java Object)實現了EJB的功能。

缺陷:雖然spring的組件代碼是輕量級的,但它的配置確是重量級的。

由此,SpringBoot應運而生,SpringBoot簡化了spring的應用開發,只需要*run*就能創建一個獨立的,生產級別的spring應用。SpringBoot為spring平台和第三方庫提供了開箱即用的設置(即:提供默認設置),只需要很少的spring配置。

可以使用SpringBoot創建Java應用,*jar部署*方式,使用java -jar啟動,也可以采用傳統的war部署方式

2、shiro

全稱為Apache Shiro,一個強大且易用的*java安全框架*,執行身份驗證,授權,密碼學和會話管理。使用shiro API,可以快速,輕松地獲得任何應用程序。包括移動應用程序或網絡和企業應用程序。

Shiro六大體系結構

Authentication認證 ——用戶登錄

Authorization授權 ——用戶具有哪些權限

Cryptography 安全數據加密

Session Management 會話管理

Web Integration web系統集成

Interations 集成其他應用,spring,緩存框架等。

3、thymeleaf /taim.li:f/

項目所用到的頁面模板,Spring Boot之前spring應用程序通常使用的都是jsp

Spring Boot推薦使用thymeleaf,thymeleaf在html頁面的基礎上添加特定標簽,來實現頁面模板的渲染。

Thymeleaf是⾯向Web和獨⽴環境的現代服務器端Java模板引擎,能夠處 理HTML,XML,JavaScript,CSS甚⾄純⽂本。 Thymeleaf旨在提供⼀個優雅的、⾼度可維護的創建模板的⽅式。

為了實 現這⼀⽬標,Thymeleaf建⽴在⾃然模板的概念上,將其邏輯注⼊到模板 ⽂件中,不會影響模板設計原型。 這改善了設計的溝通,彌合了設計和 開發團隊之間的差距。 Thymeleaf從設計之初就遵循Web標准——特別是HTML5標准 ,如果需 要,Thymeleaf允許您創建完全符合HTML5驗證標准的模板

二、快速入門

1、Spring Boot快速入門

1.1、建立maven項目,繼承Spring Boot父工程

img

繼承Spring Boot父工程

<!-- 1、創建maven項目,繼承Spring Boot父工程 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
</parent>

1.1.1、附加:Spring Boot可以方便的修改項目jdk的版本(只需要修改pom.xml的參數即可)

原始jdk

img

修改pom.xml的參數

  <!-- 附加:Spring Boot可以方便的修改項目jdk的版本 -->
<!-- 修改參數 -->
<properties>
<java.version>1.8</java.version>
</properties>

ctrl+s保存 , 右鍵項目--maven--Update Project

img

修改后的項目jdk

img

1.2、導入依賴——導入web支持:SpringMVC開發支持,Servlet相關程序支持等

  <!-- 2、導入依賴 -->
<dependencies>
<!-- 2.1、導入web支持:SpringMVC開發支持,Servlet相關程序支持等 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

1.3、編寫Controller測試類:TestController(注意controller注解)

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class TestController {

@RequestMapping("/hello") //訪問地址映射
@ResponseBody //相應體 ——return "success";
public Object hello() {
System.out.println("test------");
return "success";
}

}

1.4、編寫Spring Boot啟動類:Application——(@SpringBootApplication)SpringApplication.run(Application.class,args);

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication //啟動類注解
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

訪問形式:(即 localhost:8080/hello )

img

 

1.5、導入thymeleaf頁面模塊(引入thymeleaf依賴)

<!-- 2.2、導入thymeleaf頁面模塊依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

1.5.1、測試thymeleaf(在controller中添加測試方法)

 /*
* 測試thymeleaf頁面模塊是否可用
*/
@RequestMapping("/testThymeleaf")
public String testThymeleaf(Model model) {

//把數據存入model中
model.addAttribute("test", "thymeleaf");

//返回test.html     (return "test";)與return的值一致
return "test";

}

1.5.2、建立前端測試頁面test.html

創建的Spring Boot是jar項目,Spring boot存放頁面的地方,在src/main/resources下創建一個web頁根目錄(相當於webapp)——:templates,在此目錄下創建test.html頁面。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>測試thymeleaf頁面模塊是否可用</title>
</head>
<body>

<!-- 一個簡單的thymeleaf語法th:text="${}" -->
<h2 th:text="${test}"></h2>
</body>
</html>

問題:

img

img

原因:在thymeleaf3.0以前對頁面標簽語法要求比較嚴格,開始標簽必須有對應的結束標簽。

解決:1、將頁面中標簽語言嚴謹化

img

2、如果希望頁面語法不嚴謹,但是也能夠運行成功,可以把thymeleaf升級為3.0或以上版本。

任何版本的更改都可以通過<properties>屬性進行修改

  <!-- 2.2.1、修改thymeleaf的版本 -->
<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
<!-- 2.2.2、附帶的版本修改 -->
<thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.version>

注意:在2.2.2、附帶的版本修改中,沒有RELEASE

訪問:localhost:8080/testThymeleaf

 


2、Spring boot與Shiro整合實現用戶認證

2.1、Shiro的核心API,三個核心類

Subject:用戶主體(包括用戶登錄,注銷等方法,還有一些判斷授權的方法) (關聯SecurityManager,把操作交給它)

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

Realm:Shiro連接數據庫的橋梁

2.2、導入shiro和spring的整合依賴

   <!-- 導入shiro和spring的整合依賴 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>

2.3、在編寫Shiro配置類之前,要先自定義Realm類(用來編寫查詢的一些方法方式,或者是完成一些認證與授權的邏輯)

繼承 AuthorizingRealm(實現兩個方法,執行授權和認證邏輯)TestRealm.java

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
/**
* 自定義Realm類
* @author fzywhy
*
*/

public class TestRealm extends AuthorizingRealm {
/*
* 執行授權邏輯
* @see org.apache.shiro.realm.AuthorizingRealm#doGetAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection)
*/

@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
System.out.println("執行授權邏輯");
return null;
}

/*
* 執行認證邏輯
* @see org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken)
*/

@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
System.out.println("執行認證邏輯");
return null;
}
}

2.4、編寫Shiro配置類(spring中配置文件是ContextApplication.xml) ShiroConfig.java

(創建ShiroFilterFactoryBean,創建DefaultWebSecurityManager,創建Realm(連接數據庫)

package com.fzy.shiro;
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;

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

/*
* 創建ShiroFilterFactoryBean
*/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//設置安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
return shiroFilterFactoryBean;
}

/*
* 創建DefaultWebSecurityManager——關聯realm(連接數據庫)
*/
@Bean(name="securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("testRealm")TestRealm testRealm) {

DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//關聯realm
securityManager.setRealm(testRealm);
return securityManager;
}

/*
* 創建Realm——自定義Realm類
*/
@Bean //添加到spring容器中
public TestRealm getRealm() {
return new TestRealm();
}

}

2.5、使用Shiro內置過濾器實現頁面攔截(在ShiroConfig.java中)

 /*
* 創建ShiroFilterFactoryBean
*/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager) {

ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//設置安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
/*
* 使用Shiro內置過濾器實現頁面攔截:攔截url鏈接請求
*
* shiro內置過濾器,可以實現權限相關的攔截器
* 常用的過濾器:
* anon:無需認證(登錄)可以訪問
* authc:必須認證才可以訪問
* user:如果使用rememberMe的功能可以直接訪問 (記住用戶和密碼)
* perms:該資源必須得到資源權限才可以訪問 (密碼驗證)
* role:該資源必須得到角色權限才可以訪問 (VIP會員)
*
*/

//創建集合——充作攔截器集合
Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();

/*
* 單個url攔截,
*/
/*
filterChainDefinitionMap.put("/add", "authc");
filterChainDefinitionMap.put("/update", "authc");
*/

//批量url攔截
filterChainDefinitionMap.put("/*", "authc");

//url放行
filterChainDefinitionMap.put("/testThymeleaf", "anno");

/*
* shiro攔截器攔截成功后,會返回一個默認的地址login.jsp
* 可以自定義修改調整的登錄頁面
*/
shiroFilterFactoryBean.setLoginUrl("/toLogin");
//設置攔截器map集合
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}

2.5.1、在TestController.java中添加以下請求路徑映射(請求全部都要經過Controller,來跳轉到我們自定義的頁面模板)

 //add.html用戶添加
@RequestMapping("/add")
public String add() {
return "/user/add";
}

//update.html用戶更新
@RequestMapping("/update")
public String update() {
return "/user/update";
}
//login.html自定義的登錄頁面
@RequestMapping("/toLogin")
public String login() {
return "login";
}

2.5.2、頁面結構

img

2.5.3、在test.html中

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>測試thymeleaf頁面模塊是否可用</title>
</head>
<body>

<!-- 一個簡單的thymeleaf語法th:text="${}" -->
<h2 th:text="${test}"></h2>
用戶添加頁面<a href="add">用戶添加</a><br>
用戶更新頁面<a href="update">用戶更新</a>

</body>
</html>

2.5.4、訪問測試:localhost:8080/add或者是/update,都會被攔截,被轉發到toLogin,而/testThymeleaf可正常訪問。

2.5.5、遇到的錯誤

img

第一個紅框錯誤:getShiroFilterFactoryBean方法前,未加@Bean注解

第二個紅框錯誤:filterChainDefinitionMap.put("/testThymeleaf","ann"); 代碼錯誤,是anon不是ann

2.6、實現用戶認證(登錄)操作

2.6.1、登錄頁面login.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用戶登錄</title>
</head>
<body>

<hr>
<h1>用戶登錄</h1>
<form method="post" action="login">
用戶名<input type="text" name="name"/><br/>
密   碼<input type="password" name="password"/><br/>
<input type="submit" value="登錄"/>
</form>

</body>
</html>

2.6.2、在Controller中編寫登錄邏輯(TestController.java)

 /*
* 登錄邏輯處理
*/
@RequestMapping("/login")
public String login(String name,String password,Model model) { //name和password也可以封裝到一個user對象中,model用來返回錯誤信息
/*
* 使用Shiro編寫認證操作
* 1.獲取Subject
* 2.封裝用戶數據
* 3、執行登錄方法
*/
//1.獲取Subject
Subject subject = SecurityUtils.getSubject();
//2.封裝用戶數據
UsernamePasswordToken token = new UsernamePasswordToken(name,password);
//3.執行登錄方法
try {
subject.login(token);
/*
* 無任何異常,則登錄成功
* 跳轉到test.html頁面
*/
return "redirect:/testThymeleaf"; //redirect:重定向(不帶數據),而非轉發請求(帶數據)
} catch (UnknownAccountException e) {
//UnKnownAccountException登錄失敗:用戶名不存在
model.addAttribute("msg", "用戶名不存在");
//帶着msg數據,轉發請求
return "login";
} catch (IncorrectCredentialsException e) {
//IncorrectCredentialsException登錄失敗:密碼錯誤
model.addAttribute("msg", "密碼錯誤");
return "login";
}
}

訪問問題:localhost:8080/testThymeleaf跳轉到toLogin請求中,輸入用戶名和密碼,點擊登錄,此時是不成功的

問題原因:Shiro內置攔截器將login.html的資源攔截(批量攔截)

解決方案:在ShiroConfig.java即shiro配置類中,放行login請求

//放行login.html頁面,即放行login請求 ​ filterChainDefinitionMap.put("/login", "anon");

 

2.6.3、在Realm中編寫判斷邏輯(TestRealm.java)

 /*
* 執行認證邏輯
* @see org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken)
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
System.out.println("執行認證邏輯");
/*
* 認證邏輯
*/
//給定用戶名和密碼
String name = "fzy";
String password = "fzy";
/*
* 編寫shiro的判斷邏輯,判斷用戶名和密碼
*/
//1.判斷用戶名
UsernamePasswordToken token = (UsernamePasswordToken)arg0; //將形參強制轉換為TestController.java中封裝的數據類型
//如果用戶名不存在
if(!token.getUsername().equals(name)) {
return null; //shiro底層會拋出UnknownAccountException
}
//2.判斷密碼
return new SimpleAuthenticationInfo("", password, "");
}

2.7、與Mybatis整合實現登錄

2.7.1、導入mybatis的相關依賴(連接池,數據庫驅動,springBoot的mybatis啟動器)

   <!-- 3、導入mybatis相關依賴 -->
<!-- 3.1、數據庫導入連接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.9</version>
</dependency>
<!-- 3.2、導入MySQL數據庫驅動 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 3.3、導入spring boot的mybatis的啟動器 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>

2.7.2、在web資源根目錄下配置application.properties(web資源根目錄src/main/resources)

spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot
spring.datasource.username=root
spring.datasource.password=123456

#連接池
spring.datasource.type=com.alibaba.druid.pool.DruidDatasource
#mybatis包掃描
mybatis.type-aliases-package=com.fzy.domain

2.7.3、編寫User實體類

package com.fzy.domain;
/**
* tablename=user
* @author fzywhy
*
*/

public class User {
private Integer id;
private String name;
private String password;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

2.7.4、編寫UserMapper接口(即dao接口)

package com.fzy.mapper;

import com.fzy.domain.User;

public interface UserMapper {
public User findUserByName(String name);
}

2.7.5、編寫UserMapper.xml接口映射文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 該文件存放CRUD的sql語句 -->
<mapper namespace="com.fzy.mapper.UserMapper"> <!-- namespace:UserMapper.java的全限定類名 -->

<!-- id:接口方法名,parameterType:參數類型,resultType:方法返回類型 -->
<select id="findUserByName" parameterType="string" resultType="user">
select id,name,password
from user
where name = #{value}
</select>

</mapper>

2.7.6、編寫業務接口UserService.java

package com.fzy.service;

import com.fzy.domain.User;
public interface UserService {
public User findUserByName(String name);
}

2.7.7、編寫業務接口實現類UserServiceImpl.java(注意添加業務實現類注解@Service)

package com.fzy.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.fzy.domain.User;
import com.fzy.mapper.UserMapper;
import com.fzy.service.UserService;

@Service //業務實現類注解
public class UserServiceImpl implements UserService {
//實現類要使用mapper(即dao)接口中的方法,所以要注入mapper接口
@Autowired
private UserMapper usermapper;
@Override
public User findUserByName(String name) {
//用mapper接口對象,調用mapper接口中的方法
return usermapper.findUserByName(name);
}
}

2.7.8、在啟動類中添加mabatis掃描包注解@MapperScan("com.fzy.mapper")

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

@SpringBootApplication //啟動類注解
@MapperScan("com.fzy.mapper") //添加mapper掃描包注解
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

2.7.9、改寫自定義Realm類的執行認證邏輯

 //需要調用業務層service接口中的方法得到頁面中的數據,注入UserService
@Autowired
private UserService userService;
/*
* 執行認證邏輯
* @see org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken)
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
System.out.println("執行認證邏輯");
// /*
// * 認證邏輯
// */
// //給定用戶名和密碼
// String name = "fzy";
// String password = "fzy";
// /*
// * 編寫shiro的判斷邏輯,判斷用戶名和密碼
// */
// //1.判斷用戶名
// UsernamePasswordToken token = (UsernamePasswordToken)arg0; //將形參強制轉換為TestController.java中封裝的數據類型,即controller中傳遞來的數據
// //如果用戶名不存在
// if(!token.getUsername().equals(name)) {
// return null; //shiro底層會拋出UnknownAccountException
// }

// //2.判斷密碼 返回返回類型AuthenticationInfo的一個子類SimpleAuthenticationInfo(參數1:需要返回給login方法的數據,參數2:數據庫密碼,參數3:shiro名字)

// return new SimpleAuthenticationInfo("", password, "");
/*
* 與mybatis整合后的認證邏輯
*/
//判斷用戶名
UsernamePasswordToken token = (UsernamePasswordToken)arg0;
//得到用戶在頁面上填寫的用戶名
User user = userService.findUserByName(token.getUsername());
//如果用戶名不存在
if(user == null) {
return null; //shiro底層拋出UnknownAccountException
}
//判斷密碼 返回返回類型AuthenticationInfo的一個子類SimpleAuthenticationInfo(參數1:需要返回給login方法的數據,參數2:數據庫密碼,參數3:shiro名字)
return new SimpleAuthenticationInfo("", user.getPassword(), "");
}

注意:得到用戶名 User user = userService.findUserByName(token.getUsername()); token.

判斷密碼 return new SimpleAuthenticationInfo("",user.getPassword(),""); user.

2.7.10、注意:建立相對應的數據庫,並保存數據

3、Spring Boot與Shiro整合實現用戶授權

3.1、使用shiro內置攔截器攔截資源ShiroConfig.java

  //授權過濾器  注意:當前授權攔截后,shiro會自動跳轉到默認的未授權頁面
filterChainDefinitionMap.put("/add", "perms[user:add]"); //perms[user:add]中user:add是授權的自定義字符串
//設置未授權的提示頁面
shiroFilterFactoryBean.setUnauthorizedUrl("noAuth");

注意:授權過濾器需要添加到批量url資源攔截之前 (不然,程序流程走不到授權認證)

 /*
* 創建ShiroFilterFactoryBean
*/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//設置安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
/*
* 使用Shiro內置過濾器實現頁面攔截:攔截url鏈接請求
*
* shiro內置過濾器,可以實現權限相關的攔截器
* 常用的過濾器:
* anon:無需認證(登錄)可以訪問
* authc:必須認證才可以訪問
* user:如果使用rememberMe的功能可以直接訪問 (記住用戶和密碼)
* perms:該資源必須得到資源權限才可以訪問 (密碼驗證)
* role:該資源必須得到角色權限才可以訪問 (VIP會員)
*
*/

//創建集合——充作攔截器集合
Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();
/*
* 單個url攔截,
*/
/* filterChainDefinitionMap.put("/add", "authc");
filterChainDefinitionMap.put("/update", "authc");*/
//url放行
filterChainDefinitionMap.put("/testThymeleaf", "anon");
//放行login.html頁面,即放行login請求
filterChainDefinitionMap.put("/login", "anon");

//授權過濾器 注意:當前授權攔截后,shiro會自動跳轉到默認的未授權頁面
filterChainDefinitionMap.put("/add", "perms[user:add]"); //perms[user:add]中user:add是授權的自定義字符串

//批量url攔截
filterChainDefinitionMap.put("/*", "authc");
/*
* shiro攔截器攔截成功后,會返回一個默認的地址login.jsp
* 可以自定義修改調整的登錄頁面
*/
shiroFilterFactoryBean.setLoginUrl("/toLogin");

//設置未授權的提示頁面
shiroFilterFactoryBean.setUnauthorizedUrl("noAuth");

//設置攔截器map集合
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;

}

3.1.1、在controller中添加請求url映射noAuth

 //noAuth.html——未授權提示頁面
@RequestMapping("noAuth")
public String noAuth() {
return "/noAuth";
}

3.1.2、創建noAuth.html頁面

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>未授權提示頁面</title>
</head>
<body>
<h2>未授權,不可訪問</h2>
</body>
</html>

3.2、完成shiro的資源授權TestRealm.java

 /*
* 執行授權邏輯
* @see org.apache.shiro.realm.AuthorizingRealm#doGetAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection)
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
System.out.println("執行授權邏輯");
/*
* 給資源進行授權
*/
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//添加資源的授權字符串
info.addStringPermission("user:add"); //參數字符串與資源授權過濾器的參數值一致
return info;
}

3.3、關聯數據庫動態授權

3.3.1、修改數據庫——添加perms字段,並保存user:add和user:updata授權字符串

img

3.3.2、修改User實體類

3.3.3、添加一個mapper接口方法,根據id找到user findUserById

3.3.4、UserMapper.xml中添加對應的sql映射

3.3.5、在UserService業務接口中,添加對應的方法 findUserById

3.3.6、在UserServiceImpl業務接口實現類中,添加實現新增的方法

3.3.7、修改Realm中的授權邏輯硬編碼

 /*
* 執行授權邏輯
* @see org.apache.shiro.realm.AuthorizingRealm#doGetAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection)
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
System.out.println("執行授權邏輯");
/*
* 給資源進行授權
*/
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//添加資源的授權字符串
// info.addStringPermission("user:add"); //參數字符串與資源授權過濾器的參數值一致
/*
* 改造授權字符串硬編碼
* 到數據庫中查詢當前登錄用戶的授權字符串
*/

//獲取當前用戶
Subject subject = SecurityUtils.getSubject();

//獲取執行認證返回的principal的參數
//執行認證邏輯時判斷密碼返回的第一個參數user
User user = (User)subject.getPrincipal();

//得到user的id
User userId = userService.findUserById(user.getId());

//獲取當前用戶數據庫中給定的授權字符串,並將其添加為資源的授權字符串
info.addStringPermission(userId.getPerms());

return info;
}

注意:在執行認證邏輯判斷密碼時,要返回一個principal的參數user

  //判斷密碼  返回返回類型AuthenticationInfo的一個子類SimpleAuthenticationInfo(參數1:需要返回給login方法的數據,參數2:數據庫密碼,參數3:shiro名字)

return new SimpleAuthenticationInfo(user, user.getPassword(), "");

若忘記添加,會出現以下錯誤

img

3.3.8、補充:在ShiroConfig中為update.html添加權限過濾

filterChainDefinitionMap.put("/update", "perms[user:update]");

4、Thymeleaf和shiro標簽整合使用

4.1、導入Thymeleaf擴展坐標

  <!-- 4、導入Thymeleaf擴展坐標 -->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>

4.2、在ShiroConfig中配置ShiroDialect——在ShiroConfig類里面添加getShiroDialect方法

 /*
* 配置ShiroDialect,用於Thymeleaf和Shiro標簽配合使用
*/
@Bean
public ShiroDialect getShiroDialect() {
return new ShiroDialect();
}

4.3、修改test.html頁面中的內容(在頁面上使用shiro標簽)

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<meta charset="UTF-8">
<title>測試thymeleaf頁面模塊是否可用</title>
</head>
<body>
<!-- 一個簡單的thymeleaf語法th:text="${}" -->
<h2 th:text="${test}"></h2>
<div shiro:hasPermission="user:add">
用戶添加頁面<a href="add">用戶添加</a><br>
</div>
<div shiro:hasPermission="user:update">
用戶更新頁面<a href="update">用戶更新</a>
</div>
<a href="toLogin">登錄</a>
</body>
</html>

功能實現:用戶只能看到自己權限允許的標簽

admin用戶登錄只能看到用戶添加

lhm用戶登錄只能看到用戶更新

請求全部都要經過Controller,來跳轉到我們自定義的頁面模板

guest標簽  shiro:guest  /shiro:guest  用戶沒有身份驗證時顯示相應信息,即游客訪問信息。

user標簽  shiro:user    /shiro:user  用戶已經身份驗證/記住我登錄后顯示相應的信息。

authenticated標簽  shiro:authenticated    /shiro:authenticated  用戶已經身份驗證通過,即Subject.login登錄成功,不是記住我登錄的。

notAuthenticated標簽  shiro:notAuthenticated    /shiro:notAuthenticated  用戶已經身份驗證通過,即沒有調用Subject.login進行登錄,包括記住我自動登錄的也屬於未進行身份驗證。

principal標簽  <shiro: principal/>    <shiro:principal property="username"/>  相當於((User)Subject.getPrincipals()).getUsername()。

lacksPermission標簽  <shiro:lacksPermission name="org:create">  /shiro:lacksPermission  如果當前Subject沒有權限將顯示body體內容。

hasRole標簽  <shiro:hasRole name="admin">    /shiro:hasRole  如果當前Subject有角色將顯示body體內容。

hasAnyRoles標簽  <shiro:hasAnyRoles name="admin,user">     /shiro:hasAnyRoles  如果當前Subject有任意一個角色(或的關系)將顯示body體內容。

lacksRole標簽  <shiro:lacksRole name="abc">    /shiro:lacksRole  如果當前Subject沒有角色將顯示body體內容。 hasPermission標簽  <shiro:hasPermission name="user:create">    /shiro:hasPermission  如果當前Subject有權限將顯示body體內容


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM