權(quán)限框架之Shiro詳解(非原創(chuàng))

文章大綱

一骨稿、權(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

五戈擒、參考文章

  1. https://www.cnblogs.com/jpfss/p/8352031.html
  2. https://blog.csdn.net/liyuejin/article/details/77838868
  3. http://yun.itheima.com/open/283.html?1810mcgqq
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末眶明,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子筐高,更是在濱河造成了極大的恐慌搜囱,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件柑土,死亡現(xiàn)場離奇詭異蜀肘,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)稽屏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門扮宠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人狐榔,你說我怎么就攤上這事坛增。” “怎么了薄腻?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵收捣,是天一觀的道長。 經(jīng)常有香客問我庵楷,道長罢艾,這世上最難降的妖魔是什么楣颠? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮咐蚯,結(jié)果婚禮上童漩,老公的妹妹穿的比我還像新娘。我一直安慰自己仓蛆,他們只是感情好睁冬,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著看疙,像睡著了一般豆拨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上能庆,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天施禾,我揣著相機(jī)與錄音,去河邊找鬼搁胆。 笑死弥搞,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的渠旁。 我是一名探鬼主播攀例,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼顾腊!你這毒婦竟也來了粤铭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤杂靶,失蹤者是張志新(化名)和其女友劉穎梆惯,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吗垮,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡垛吗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了烁登。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片怯屉。...
    茶點(diǎn)故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖饵沧,靈堂內(nèi)的尸體忽然破棺而出蚀之,到底是詐尸還是另有隱情,我是刑警寧澤捷泞,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站寿谴,受9級特大地震影響锁右,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一咏瑟、第九天 我趴在偏房一處隱蔽的房頂上張望拂到。 院中可真熱鬧,春花似錦码泞、人聲如沸兄旬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽领铐。三九已至,卻和暖如春宋舷,著一層夾襖步出監(jiān)牢的瞬間绪撵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工祝蝠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留音诈,地道東北人。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蒿赢。 傳聞我的和親對象是個殘疾皇子娄徊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容