1. 程式人生 > 其它 >Springboot整合shiro(簡單入門)

Springboot整合shiro(簡單入門)

技術標籤:Springbootshirospring資料庫

整合Shiro:

spring-boot 與 shiro整合的pom.xml檔案(一般都和資料庫聯用)

		
        <!-- shiro整合spring的包-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring-boot-web-starter</artifactId>
            <
version
>
1.7.1</version> </dependency> <!-- mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.4</version> </
dependency
>
<!-- jdbc--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!-- JDBC驅動--> <dependency> <groupId>org.springframework.boot</
groupId
>
<artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!-- 連線myal驅動--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <!-- druid資料來源--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.4</version> </dependency> <!-- 匯入log4j--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>

具體思想要檢視這個圖
Shiro的核心三個物件:
在這裡插入圖片描述
在這裡插入圖片描述

可以看到:應用程式碼直接互動的物件是 Subject,也就是說 Shiro 的對外 API 核心就是 Subject;其每個 API 的含義:

Subject:主體,代表了當前 “使用者”,這個使用者不一定是一個具體的人,與當前應用互動的任何東西都是 Subject,如網路爬蟲,機器人等;即一個抽象概念;所有 Subject 都繫結到 SecurityManager,與 Subject 的所有互動都會委託給 SecurityManager;可以把 Subject 認為是一個門面;SecurityManager 才是實際的執行者;

SecurityManager:安全管理器;即所有與安全有關的操作都會與 SecurityManager 互動;且它管理著所有 Subject;可以看出它是 Shiro 的核心,它負責與後邊介紹的其他元件進行互動,如果學習過 SpringMVC,你可以把它看成 DispatcherServlet 前端控制器;

Realm:域,Shiro 從從 Realm 獲取安全資料(如使用者、角色、許可權),就是說 SecurityManager 要驗證使用者身份,那麼它需要從 Realm 獲取相應的使用者進行比較以確定使用者身份是否合法;也需要從 Realm 得到使用者相應的角色 / 許可權進行驗證使用者是否能進行操作;可以把 Realm 看成 DataSource,即安全資料來源。

資料表(擁有perms許可權欄位):
在這裡插入圖片描述

注意:shiro中的配置類和Realm的實體類都是缺一不可的,一個是配置,注入到IOC容器中,另一個是處理和授權
和之前自定義的WebConfig一樣,建立要給ShiroConfig的配置類

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
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 java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    @Bean
    //ShiroFilterFactoryBean:3
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //設定安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //新增shiro的內建過濾器
        /*
            anon : 無需認證就可以訪問
            authc: 必須認證了才能訪問
            user: 必須擁有記住我 功能才能訪問
            perms: 擁有對某個資源的許可權才能訪問
            role: 擁有某個角色許可權才能訪問
         */

        Map<String, String> filterMap = new LinkedHashMap<>();

        //進行許可權的操作,正常情況下,沒有授權會跳轉到未授權的介面
        //perms[user:add] : 必須是user使用者並且有add許可權才能執行這個/user/add操作
        //perms[user:update]: 必須是user使用者並且有update許可權才能執行/user/update操作
        filterMap.put("/user/add","perms[user:add]");
        filterMap.put("/user/update","perms[user:update]");

        //進行攔截的操作
        //存放的為: 請求 + 認證
//        filterMap.put("/user/add","authc");
//        filterMap.put("/user/update","authc");
        filterMap.put("/user/*","authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        //設定登入的請求
        shiroFilterFactoryBean.setLoginUrl("/toLogin");
        //設定未授權的頁面
        shiroFilterFactoryBean.setUnauthorizedUrl("/noAuthorized");


        return shiroFilterFactoryBean;
    }

    //DefaultWebSecurityManager:2
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //需要關聯Realm
        securityManager.setRealm(userRealm);
        return securityManager;
    }


    // 建立 realm物件,需要自定義:1

    @Bean  //這個userRealm,放入到IOC容器當中,方法名就是bean的名字
    public UserRealm userRealm(){
        return new UserRealm();
    }


    //整合ShiroDialect: 用來整合 shiro 與 thymeleaf
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }

同時對於角色的授權和認證操作,都是Realm的實體類中(配合資料庫進行操作):

//自定義的userRealm extends AuthorizingRealm
public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    //授權
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("執行了=>授權doGetAuthorizationInfo");
        //授權 :SimpleAuthorizationInfo
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        //info.addStringPermission("user:add");

        //拿到當前登入的這個物件
        Subject subject = SecurityUtils.getSubject();

        //拿到User物件
        User currentUser = (User)subject.getPrincipal();

        //設定當前的使用者
        info.addStringPermission(currentUser.getPerms());


        return info;
    }

    //認證
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("執行了=>認證doGetAuthenticationInfo");

        //使用者名稱,密碼 --- 沒有,從資料庫中取得
//        String name = "root";
//        String password = "123456";



        //這個token是全域性存在的,只要儲存下來了,就能夠獲得
        UsernamePasswordToken userToken = (UsernamePasswordToken) token;

        //從資料庫中獲得資料
        //連線真實資料庫
        User user = userService.queryUserByName(userToken.getUsername());
        //如果使用者不存在
        if(user == null){
            return null; //自動丟擲異常 UnknownAccountException
        }

        //可以加密 : MD5鹽值加密
        //密碼認證,shiro自動幫我們做, 加密了
        return new SimpleAuthenticationInfo(user,user.getPwd(),"");
    }
}