一、簡介
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父工程
繼承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
修改pom.xml的參數
<!-- 附加:Spring Boot可以方便的修改項目jdk的版本 -->
<!-- 修改參數 -->
<properties>
<java.version>1.8</java.version>
</properties>
ctrl+s保存 , 右鍵項目--maven--Update Project
修改后的項目jdk
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 )
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>
問題:
原因:在thymeleaf3.0以前對頁面標簽語法要求比較嚴格,開始標簽必須有對應的結束標簽。
解決:1、將頁面中標簽語言嚴謹化
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、頁面結構
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、遇到的錯誤
第一個紅框錯誤: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;
}
//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授權字符串
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(), "");
若忘記添加,會出現以下錯誤
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標簽)
功能實現:用戶只能看到自己權限允許的標簽
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