文章大綱
一骨稿、權(quán)限框架介紹
二泽本、Shiro基礎(chǔ)介紹
三、Spring Boot整合Shiro代碼實(shí)戰(zhàn)
四捻爷、項(xiàng)目源碼與資料下載
五辈灼、參考文章
一、權(quán)限框架介紹
1. 什么是權(quán)限管理
??權(quán)限管理屬于系統(tǒng)安全的范疇也榄,權(quán)限管理實(shí)現(xiàn)對用戶訪問系統(tǒng)的控制巡莹,按照安全規(guī)則或者安全策略控制用戶可以訪問而且只能訪問自己被授權(quán)的資源。
??權(quán)限管理包括用戶身份認(rèn)證和授權(quán)兩部分甜紫,簡稱認(rèn)證授權(quán)降宅。對于需要訪問控制的資源用戶首先經(jīng)過身份認(rèn)證,認(rèn)證通過后用戶具有該資源的訪問權(quán)限方可訪問囚霸。
1.1 用戶身份認(rèn)證
??身份認(rèn)證腰根,就是判斷一個用戶是否為合法用戶的處理過程。最常用的簡單身份認(rèn)證方式是系統(tǒng)通過核對用戶輸入的用戶名和口令拓型,看其是否與系統(tǒng)中存儲的該用戶的用戶名和口令一致额嘿,來判斷用戶身份是否正確。對于采用指紋等系統(tǒng)劣挫,則出示指紋册养;對于硬件Key等刷卡系統(tǒng),則需要刷卡压固。
用戶名密碼身份認(rèn)證流程:
1.2 授權(quán)流程
??授權(quán)球拦,即訪問控制,控制誰能訪問哪些資源帐我。主體進(jìn)行身份認(rèn)證后需要分配權(quán)限方可訪問系統(tǒng)的資源坎炼,對于某些資源沒有權(quán)限是無法訪問的。
2. 常見權(quán)限框架
2.1 Shiro簡介
??Apache Shiro是Java的一個安全框架拦键。目前谣光,使用Apache Shiro的人越來越多,因?yàn)樗喈?dāng)簡單矿咕,對比Spring Security抢肛,可能沒有Spring Security做的功能強(qiáng)大,但是在實(shí)際工作時可能并不需要那么復(fù)雜的東西碳柱,所以使用小而簡單的Shiro就足夠了捡絮。對于它倆到底哪個好,這個不必糾結(jié)莲镣,能更簡單的解決項(xiàng)目問題就好了福稳。
2.2 Spring Security
??Spring Security是一個能夠?yàn)榛赟pring的企業(yè)應(yīng)用系統(tǒng)提供聲明式的安全訪問控制解決方案的安全框架。它提供了一組可以在Spring應(yīng)用上下文中配置的Bean瑞侮,充分利用了Spring IoC的圆,DI(控制反轉(zhuǎn)Inversion of Control ,DI:Dependency Injection 依賴注入)和AOP(面向切面編程)功能鼓拧,為應(yīng)用系統(tǒng)提供聲明式的安全訪問控制功能,減少了為企業(yè)系統(tǒng)安全控制編寫大量重復(fù)代碼的工作越妈。它是一個輕量級的安全框架季俩,它確保基于Spring的應(yīng)用程序提供身份驗(yàn)證和授權(quán)支持梅掠。它與Spring MVC有很好地集成酌住,并配備了流行的安全算法實(shí)現(xiàn)捆綁在一起。安全主要包括兩個操作“認(rèn)證”與“驗(yàn)證”(有時候也會叫做權(quán)限控制)阎抒±椅遥“認(rèn)證”是為用戶建立一個其聲明的角色的過程,這個角色可以一個用戶且叁、一個設(shè)備或者一個系統(tǒng)都哭。“驗(yàn)證”指的是一個用戶在你的應(yīng)用中能夠執(zhí)行某個操作逞带。在到達(dá)授權(quán)判斷之前欺矫,角色已經(jīng)在身份認(rèn)證過程中建立了。
2.3 Shiro和Spring Security比較
(1)Shiro比Spring更容易使用掰担,實(shí)現(xiàn)和最重要的理解
(2)Spring Security更加知名的唯一原因是因?yàn)槠放泼Q
(3)“Spring”以簡單而聞名汇陆,但諷刺的是很多人發(fā)現(xiàn)安裝Spring Security很難
(4)Spring Security卻有更好的社區(qū)支持
(5)Apache Shiro在Spring Security處理密碼學(xué)方面有一個額外的模塊
(6)Spring-security 對spring 結(jié)合較好,如果項(xiàng)目用的springmvc 带饱,使用起來很方便。但是如果項(xiàng)目中沒有用到spring阅羹,那就不要考慮它了勺疼。
(7)Shiro 功能強(qiáng)大、且 簡單捏鱼、靈活执庐。是Apache 下的項(xiàng)目比較可靠,且不跟任何的框架或者容器綁定导梆,可以獨(dú)立運(yùn)行
二轨淌、Shiro基礎(chǔ)介紹
1. Shiro三個核心組件
1.1 Subject
??Subject:即“當(dāng)前操作用發(fā)戶”。但是看尼,在Shiro中递鹉,Subject這一概念并不僅僅指人,也可以是第三方進(jìn)程藏斩、后臺帳戶(Daemon Account)或其他類似事物躏结。它僅僅意味著“當(dāng)前跟軟件交互的東西”。但考慮到大多數(shù)目的和用途狰域,你可以把它認(rèn)為是Shiro的“用戶”概念媳拴。Subject代表了當(dāng)前用戶的安全操作黄橘,SecurityManager則管理所有用戶的安全操作。
1.2 SecurityManager
??SecurityManager:它是Shiro框架的核心屈溉,典型的Facade模式塞关,Shiro通過SecurityManager來管理內(nèi)部組件實(shí)例,并通過它來提供安全管理的各種服務(wù)子巾。
1.3 Realm
??Realm充當(dāng)了Shiro與應(yīng)用安全數(shù)據(jù)間的“橋梁”或者“連接器”帆赢。也就是說,當(dāng)對用戶執(zhí)行認(rèn)證(登錄)和授權(quán)(訪問控制)驗(yàn)證時砰左,Shiro會從應(yīng)用配置的Realm中查找用戶及其權(quán)限信息匿醒。
??從這個意義上講,Realm實(shí)質(zhì)上是一個安全相關(guān)的DAO:它封裝了數(shù)據(jù)源的連接細(xì)節(jié)缠导,并在需要時將相關(guān)數(shù)據(jù)提供給Shiro廉羔。當(dāng)配置Shiro時,你必須至少指定一個Realm僻造,用于認(rèn)證和(或)授權(quán)憋他。配置多個Realm是可以的,但是至少需要一個髓削。
??Shiro內(nèi)置了可以連接大量安全數(shù)據(jù)源(又名目錄)的Realm竹挡,如LDAP、關(guān)系數(shù)據(jù)庫(JDBC)立膛、類似INI的文本配置資源以及屬性文件等揪罕。如果缺省的Realm不能滿足需求,你還可以插入代表自定義數(shù)據(jù)源的自己的Realm實(shí)現(xiàn)宝泵。
2. Shiro相關(guān)類介紹
(1)Authentication 認(rèn)證 ---- 用戶登錄
(2)Authorization 授權(quán) --- 用戶具有哪些權(quán)限
(3)Cryptography 安全數(shù)據(jù)加密
(4)Session Management 會話管理
(5)Web Integration web系統(tǒng)集成
(6)Interations 集成其它應(yīng)用好啰,spring、緩存框架
3. Shiro 特點(diǎn)
(1)易于理解的 Java Security API儿奶;
(2)簡單的身份認(rèn)證(登錄)框往,支持多種數(shù)據(jù)源(LDAP,JDBC闯捎,Kerberos椰弊,ActiveDirectory 等);
(3)對角色的簡單的簽權(quán)(訪問控制)瓤鼻,支持細(xì)粒度的簽權(quán)秉版;
(4)支持一級緩存,以提升應(yīng)用程序的性能娱仔;
(5)內(nèi)置的基于 POJO 企業(yè)會話管理沐飘,適用于 Web 以及非 Web 的環(huán)境;
(6)異構(gòu)客戶端會話訪問;
(7)非常簡單的加密 API耐朴;
(8)不跟任何的框架或者容器捆綁借卧,可以獨(dú)立運(yùn)行
三、Spring Boot整合Shiro代碼實(shí)戰(zhàn)
1. Spring Boot基礎(chǔ)
https://www.cnblogs.com/WUXIAOCHANG/p/10877266.html
2. 創(chuàng)建Spring Boot的基礎(chǔ)項(xiàng)目
2.1 新建maven項(xiàng)目
創(chuàng)建后項(xiàng)目結(jié)構(gòu)如下:
2.2 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的默認(rèn)父工程 -->
<!-- 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>
<!-- 導(dǎo)入依賴 -->
<dependencies>
<!-- 導(dǎo)入web支持:SpringMVC開發(fā)支持筛峭,Servlet相關(guān)的程序 -->
<!-- web支持铐刘,SpringMVC, Servlet支持等 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<!-- 修改參數(shù) -->
<properties>
<!-- 修改JDK的編譯版本為1.8 -->
<java.version>1.8</java.version>
</properties>
</project>
2.3 編寫測試Controller類
com.itheima.controller包下新建UserController.java
package com.itheima.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class UserController {
/**
* 測試方法
*/
@RequestMapping("/hello")
@ResponseBody
public String hello(){
System.out.println("UserController.hello()");
return "ok";
}
}
2.4 導(dǎo)入thymeleaf頁面模塊
pom.xml文件中添加依賴
<!-- 導(dǎo)入thymeleaf依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
UserController.java類中添加測試方法
/**
* 測試thymeleaf
*/
@RequestMapping("/testThymeleaf")
public String testThymeleaf(Model model){
//把數(shù)據(jù)存入model
model.addAttribute("name", "吳先生");
//返回test.html
return "test";
}
2.5 添加thymeleaf頁面模塊
在src/main/resource目錄下創(chuàng)建templates目錄影晓,然后創(chuàng)建test.html頁面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>測試Thymeleaf的使用</title>
</head>
<body>
<h3 th:text="${name}"></h3>
</body>
</html>
2.6 運(yùn)行項(xiàng)目并訪問
運(yùn)行項(xiàng)目
訪問項(xiàng)目
3. Spring Boot與Shiro整合實(shí)現(xiàn)用戶認(rèn)證
3.1 分析Shiro的核心API
Subject: 用戶主體(把操作交給SecurityManager)
SecurityManager:安全管理器(關(guān)聯(lián)Realm)
Realm:Shiro連接數(shù)據(jù)的橋梁
3.2 導(dǎo)入shiro與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的默認(rèn)父工程 -->
<!-- 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>
<!-- 導(dǎo)入依賴 -->
<dependencies>
<!-- 導(dǎo)入web支持:SpringMVC開發(fā)支持镰吵,Servlet相關(guān)的程序 -->
<!-- web支持,SpringMVC挂签, Servlet支持等 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 導(dǎo)入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>
<!-- 導(dǎo)入mybatis相關(guān)的依賴 -->
<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的擴(kuò)展坐標(biāo) -->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
</dependencies>
<!-- 修改參數(shù) -->
<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>
<build>
<!--解決項(xiàng)目運(yùn)行后mapper.xmlw文件找不到情況-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
</project>
3.3 resources下配置
新建application.properties文件
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/shiro_test
spring.datasource.username=root
spring.datasource.password=147258qq
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
mybatis.type-aliases-package=com.itheima.domain
templates文件夾下加入相關(guān)模板頁面
add.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用戶添加頁面</title>
</head>
<body>
用戶添加
</body>
</html>
update.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用戶更新頁面</title>
</head>
<body>
用戶更新
</body>
</html>
login.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登錄頁面</title>
</head>
<body>
<h3>登錄</h3>
<h3 th:text="${msg}" style="color: red"></h3>
<form method="post" action="login">
用戶名:<input type="text" name="name"/><br/>
密碼:<input type="password" name="password"/><br/>
<input type="submit" value="登錄"/>
</form>
</body>
</html>
noAuth.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>未授權(quán)提示頁面</title>
</head>
<body>
親疤祭,你未經(jīng)授權(quán)訪問該頁面
</body>
</html>
3.4 新建shiro相關(guān)配置
com.itheima.shiro包下新建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的配置類
*
* 關(guān)于Configuration的講解,可參考一下博客:https://www.cnblogs.com/WUXIAOCHANG/p/10877266.html
* @author lenovo
*
*/
@Configuration
public class ShiroConfig {
/**
* 創(chuàng)建ShiroFilterFactoryBean
*/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//設(shè)置安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
//添加Shiro內(nèi)置過濾器
/**
* Shiro內(nèi)置過濾器饵婆,可以實(shí)現(xiàn)權(quán)限相關(guān)的攔截器
* 常用的過濾器:
* anon: 無需認(rèn)證(登錄)可以訪問
* authc: 必須認(rèn)證才可以訪問
* user: 如果使用rememberMe的功能可以直接訪問
* perms: 該資源必須得到資源權(quán)限才可以訪問
* role: 該資源必須得到角色權(quán)限才可以訪問
*/
Map<String,String> filterMap = new LinkedHashMap<String,String>();
/*filterMap.put("/add", "authc");
filterMap.put("/update", "authc");*/
filterMap.put("/testThymeleaf", "anon");
//放行l(wèi)ogin.html頁面
filterMap.put("/login", "anon");
//授權(quán)過濾器
//注意:當(dāng)前授權(quán)攔截后勺馆,shiro會自動跳轉(zhuǎn)到未授權(quán)頁面
//perms括號中的內(nèi)容是權(quán)限的值
filterMap.put("/add", "perms[user:add]");
filterMap.put("/update", "perms[user:update]");
filterMap.put("/*", "authc");
//修改調(diào)整的登錄頁面
shiroFilterFactoryBean.setLoginUrl("/toLogin");
//設(shè)置未授權(quán)提示頁面
shiroFilterFactoryBean.setUnauthorizedUrl("/noAuth");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
return shiroFilterFactoryBean;
}
/**
* 創(chuàng)建DefaultWebSecurityManager
*
* 里面主要定義了登錄,創(chuàng)建subject侨核,登出等操作
*/
@Bean(name="securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//關(guān)聯(lián)realm
securityManager.setRealm(userRealm);
return securityManager;
}
/**
* 創(chuàng)建Realm
*/
@Bean(name="userRealm")
public UserRealm getRealm(){
return new UserRealm();
}
/**
* 配置ShiroDialect草穆,用于thymeleaf和shiro標(biāo)簽配合使用
*/
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
}
com.itheima.shiro包下新建UserRealm.java類
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
* (1)AuthenticatingRealm:shiro中的用于進(jìn)行認(rèn)證的領(lǐng)域,實(shí)現(xiàn)doGetAuthentcationInfo方法實(shí)現(xiàn)用戶登錄時的認(rèn)證邏輯搓译;
* (2)AuthorizingRealm:shiro中用于授權(quán)的領(lǐng)域悲柱,實(shí)現(xiàn)doGetAuthrozitionInfo方法實(shí)現(xiàn)用戶的授權(quán)邏輯,AuthorizingRealm繼承了AuthenticatingRealm些己,
* 所以在實(shí)際使用中主要用到的就是這個AuthenticatingRealm類豌鸡;
* (3)AuthenticatingRealm、AuthorizingRealm這兩個類都是shiro中提供了一些線程的realm接口
* (4)在與spring整合項(xiàng)目中段标,shiro的SecurityManager會自動調(diào)用這兩個方法直颅,從而實(shí)現(xiàn)認(rèn)證和授權(quán),可以結(jié)合shiro的CacheManager將認(rèn)證和授權(quán)信息保存在緩存中怀樟,
* 這樣可以提高系統(tǒng)的處理效率。
*
*/
public class UserRealm extends AuthorizingRealm{
@Autowired
private UserService userSerivce;
/**
* 執(zhí)行認(rèn)證邏輯
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
System.out.println("執(zhí)行認(rèn)證邏輯");
//編寫shiro判斷邏輯盆佣,判斷用戶名和密碼
//1.判斷用戶名 token中的用戶信息是登錄時候傳進(jìn)來的
UsernamePasswordToken token = (UsernamePasswordToken)arg0;
User user = userSerivce.findByName(token.getUsername());
if(user==null){
//用戶名不存在
return null;//shiro底層會拋出UnKnowAccountException
}
//2.判斷密碼
//第二個字段是user.getPassword()往堡,注意這里是指從數(shù)據(jù)庫中獲取的password。第三個字段是realm共耍,即當(dāng)前realm的名稱虑灰。
//這塊對比邏輯是先對比username,但是username肯定是相等的痹兜,所以真正對比的是password穆咐。
//從這里傳入的password(這里是從數(shù)據(jù)庫獲取的)和token(filter中登錄時生成的)中的password做對比,如果相同就允許登錄,
// 不相同就拋出IncorrectCredentialsException異常对湃。
//如果認(rèn)證不通過崖叫,就不會執(zhí)行下面的授權(quán)方法了
return new SimpleAuthenticationInfo(user,user.getPassword(),"");
}
/**
* 執(zhí)行授權(quán)邏輯
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
//doGetAuthorizationInfo方法可能會執(zhí)行多次,權(quán)限判斷次數(shù)多少拍柒,就會執(zhí)行多少次
System.out.println("執(zhí)行授權(quán)邏輯1");
System.out.println("執(zhí)行授權(quán)邏輯2");
//給資源進(jìn)行授權(quán)
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//添加資源的授權(quán)字符串
//info.addStringPermission("user:add");
//到數(shù)據(jù)庫查詢當(dāng)前登錄用戶的授權(quán)字符串
//獲取當(dāng)前登錄用戶
Subject subject = SecurityUtils.getSubject();
User user = (User)subject.getPrincipal();
User dbUser = userSerivce.findById(user.getId());
info.addStringPermission(dbUser.getPerms());
return info;
}
}
3.5 新建實(shí)體類
com.itheima.domain包下新建User.java
package com.itheima.domain;
public class User {
private Integer id;
private String name;
private String password;
private String perms;
public String getPerms() {
return perms;
}
public void setPerms(String perms) {
this.perms = perms;
}
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;
}
}
3.6 創(chuàng)建mapper相關(guān)內(nèi)容
com.itheima.mapper包下新建UserMapper.java
package com.itheima.mapper;
import com.itheima.domain.User;
public interface UserMapper {
public User findByName(String name);
public User findById(Integer id);
}
com.itheima.mapper包下新建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.itheima.mapper.UserMapper">
<select id="findByName" parameterType="string" resultType="user">
SELECT id,
NAME,
PASSWORD
FROM
user where name = #{value}
</select>
<select id="findById" parameterType="int" resultType="user">
SELECT id,
NAME,
PASSWORD,
perms
FROM
user where id = #{value}
</select>
</mapper>
3.7 創(chuàng)建業(yè)務(wù)邏輯相關(guān)內(nèi)容
com.itheima.service下新建UserService.java
package com.itheima.service;
import com.itheima.domain.User;
public interface UserService {
public User findByName(String name);
public User findById(Integer id);
}
com.itheima.service.impl下新建UserServiceImpl.java
package com.itheima.service.impl;
import org.apache.tomcat.util.net.openssl.ciphers.Authentication;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.itheima.domain.User;
import com.itheima.mapper.UserMapper;
import com.itheima.service.UserService;
@Service
public class UserServiceImpl implements UserService{
//注入Mapper接口
@Autowired
private UserMapper userMapper;
@Override
public User findByName(String name) {
return userMapper.findByName(name);
}
@Override
public User findById(Integer id) {
return userMapper.findById(id);
}
}
3.8 新建Controller相關(guān)內(nèi)容
UserController.java添加相關(guān)代碼心傀,最終內(nèi)容如下:
package com.itheima.controller;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.itheima.service.UserService;
@Controller
public class UserController {
/**
* 測試方法
*/
@RequestMapping("/hello")
@ResponseBody
public String hello(){
System.out.println("UserController.hello()");
return "ok";
}
@RequestMapping("/add")
public String add(){
return "/user/add";
}
@RequestMapping("/update")
public String update(){
return "/user/update";
}
@RequestMapping("/toLogin")
public String toLogin(){
return "/login";
}
@RequestMapping("/noAuth")
public String noAuth(){
return "/noAuth";
}
/**
* 測試thymeleaf
*/
@RequestMapping("/testThymeleaf")
public String testThymeleaf(Model model){
//把數(shù)據(jù)存入model
model.addAttribute("name", "吳先生");
//返回test.html
return "test";
}
/**
* 登錄邏輯處理
*/
@RequestMapping("/login")
public String login(String name,String password,Model model){
System.out.println("name="+name);
/**
* 使用Shiro編寫認(rèn)證操作
*/
//1.獲取Subject
Subject subject = SecurityUtils.getSubject();
//2.封裝用戶數(shù)據(jù)
UsernamePasswordToken token = new UsernamePasswordToken(name,password);
//3.執(zhí)行登錄方法
try {
subject.login(token);
//登錄成功
//跳轉(zhuǎn)到test.html
return "redirect:/testThymeleaf";
} catch (UnknownAccountException e) {
//e.printStackTrace();
//登錄失敗:用戶名不存在,UnknownAccountException是Shiro拋出的找不到用戶異常
model.addAttribute("msg", "用戶名不存在");
return "login";
}catch (IncorrectCredentialsException e) {
//e.printStackTrace();
//登錄失敗:密碼錯誤拆讯,IncorrectCredentialsException是Shiro拋出的密碼錯誤異常
model.addAttribute("msg", "密碼錯誤");
return "login";
}
}
}
3.9 Application啟動類配置
package com.itheima;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* SpringBoot啟動類
* @author lenovo
*
*/
@SpringBootApplication
//之前是脂男,直接在Mapper類上面添加注解@Mapper,這種方式要求每一個mapper類都需要添加此注解种呐,麻煩
//通過使用@MapperScan可以指定要掃描的Mapper類的包的路徑 同時,使用@MapperScan注解多個包
@MapperScan("com.itheima.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
3.10 創(chuàng)建后項(xiàng)目結(jié)構(gòu)
3.11 數(shù)據(jù)庫配置
數(shù)據(jù)庫的sql文件可以在項(xiàng)目源碼與資料下載中獲取宰翅,我們創(chuàng)建的數(shù)據(jù)庫名字為shiro_test,具體字段參數(shù)如下圖所示:
往數(shù)據(jù)庫插入一條數(shù)據(jù)
3.12 運(yùn)行項(xiàng)目并訪問
訪問http://localhost:8080/add或者http://localhost:8080/update,可以看到被攔截了爽室,重定向到了登錄頁面
訪問http://localhost:8080/login汁讼,進(jìn)行登錄
登錄成功
我們在數(shù)據(jù)庫添加的權(quán)限是修改的,我們試試登錄后肮之,訪問添加頁面
可以看到掉缺,已經(jīng)被攔截了
四、項(xiàng)目源碼與資料下載
鏈接:https://pan.baidu.com/s/12yTMozR6oFG6cYcVmnBwog
提取碼:yswz