shiro 實現用戶登陸認證授權


認證流程

  1. 首先調用Subject.login(token)進行登錄,其會自動委托給Security Manager,調用之前必須通過

    SecurityUtils. setSecurityManager()設置;
  2. SecurityManager負責真正的身份驗證邏輯;它會委托給Authenticator進行身份驗證;
  3. Authenticator才是真正的身份驗證者,Shiro API中核心的身份認證入口點,此處可以自定義插入自己的實
    現;
  4. Authenticator可能會委托給相應的AuthenticationStrategy進行多Realm身份驗證,默認
    ModularRealmAuthenticator會調用AuthenticationStrategy進行多Realm身份驗證;
  5. Authenticator會把相應的token傳入Realm,從Realm獲取身份驗證信息,如果沒有返回/拋出異常表示身份
    驗證失敗了。此處可以配置多個Realm,將按照相應的順序及策略進行訪問。

授權流程

  1. 首先調用Subject.isPermitted/hasRole接口,其會委托給SecurityManager,而SecurityManager接着會委托

    給Authorizer;
  2. Authorizer是真正的授權者,如果我們調用如isPermitted(“user:view”),其首先會通過PermissionResolver
    把字符串轉換成相應的Permission實例;
  3. 在進行授權之前,其會調用相應的Realm獲取Subject相應的角色/權限用於匹配傳入的角色/權限;
  4. Authorizer會判斷Realm的角色/權限是否和傳入的匹配,如果有多個Realm,會委托給
    ModularRealmAuthorizer進行循環判斷,如果匹配如isPermitted/hasRole會返回true,否則返回false表示
    授權失敗。
 

1.自定義realms 類

  必須繼承 AuthorizingRealm 抽象類

package com.zhao;

import org.apache.shiro.authc.*;
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 java.util.ArrayList;
import java.util.List;

/**
 * 自定義realms 對象
 *  繼承 AuthorizingRealm
 */
public class RealmDemo extends AuthorizingRealm {
    /**
     * 設置 RealmDemo 名字 ,自定義realms 對象 過多時避免重復
     * @param name
     */
    @Override
    public void setName(String name) {
        super.setName("realmDemo");
    }

    /**
     * 授權
     * 獲取到用戶的授權數據(用戶的權限數據)
     * 根據認證的用戶 獲取到他的權限信息
     * @param principals 包含了所有的已認證的安全數據
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println(" 授權 AuthorizationInfo ");
        //1.獲取安全數據 username ,有可能是用戶id
        String primaryPrincipal = (String)principals.getPrimaryPrincipal();
        //2.根據 username  或者id查詢用戶
        //3.查詢用戶的角色 和權限信息
        //權限
        List<String> perms =new ArrayList<>();
        perms.add("user:save");
        perms.add("user:find");
        //角色
        List<String> roles =new ArrayList<>();
        roles.add("ordinary");
        roles.add("admin");
        //4.構造返回
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        //設置權限集合
        info.addStringPermissions(perms);
        //設置角色集合
        info.addRoles(roles);
        return info;
    }

    /**
     * 認證
     * 根據用戶名密碼進行登錄,登錄之后將用戶數據進行保存
     * 認證的目的,比較用戶名和密碼是否與數據庫中的一致
     * 將安全數據存入到shiro進行保管
     * @param authenticationToken 登錄構造的 UsernamePasswordToken
     * @return AuthenticationInfo  授權數據
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println(" 認證 AuthenticationInfo ");
        //1. 構造  UsernamePasswordToken
        UsernamePasswordToken uptoken=(UsernamePasswordToken)authenticationToken;
        //2.獲取輸入的用戶名密碼
        String username = uptoken.getUsername();
        String password = new String(uptoken.getPassword());
        //3.根據用戶名查詢數據
        //4.比較密碼和數據庫中的密碼是否一致(密碼可能需要加密)
        if(username.equals("張三")&&password.equals("123456")){
            //5.成功 向 shiro存入數據
            /**
             * *@param principal與指定領域關聯的“primary”主體。 安全數據
             * *@param credentials驗證給定主體的憑據。    密碼
             * *@param realmName從中獲取主體和憑據的域。 當前realm 名稱  getName()  獲取到的是當前realm的名稱 ,他的父類方法
             */
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username,password,getName());
            return  simpleAuthenticationInfo;
        }else {
            //6.失敗 返回null 或者拋出 自定義的異常

            return null;
        }


    }
}
自定義realm類

2.配置文件

[main]
permRealm=com.zhao.RealmDemo
#注冊realm到securityManager
securityManager.realms=$permRealm
View Code

3.測試

package com.zhao.shiro.test;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Before;
import org.junit.Test;

public class ShiroTest3 {
    @Before
    public void  init(){
        // 1.根據配置文件shiroDemo.ini 文件 創建 SecurityManagerFactor
        Factory<SecurityManager>  factory= new IniSecurityManagerFactory("classpath:shiroDemoRealm.ini");
        //2.通過工廠獲取SecurityManager
        SecurityManager securityManager = factory.getInstance();
        //* 3.將SecurityManager綁定到當前運行環境
        SecurityUtils.setSecurityManager(securityManager);

    }

    /**
     * 測試用戶登錄
     * 用戶認證
     * 1.根據配置文件shiroDemo.ini 文件 創建 SecurityManagerFactor
     * 2.通過工廠獲取SecurityManager
     * 3.將SecurityManager綁定到當前運行環境
     * 4.從當前環境中構造subject
     * 5.構造shiro登陸的數據
     * 6.主題登錄
     */
    @Test
    public void  login1(){
        //* 4.從當前環境中構造subject

        Subject subject = SecurityUtils.getSubject();
       //  * 5.構造用戶認證的數據
//        String userName="lisi";
//        String password = "10086";
        String userName="張三";
       String password = "123456";
        UsernamePasswordToken token =new UsernamePasswordToken(userName,password);

        // * 6.主題登錄
        //執行 login1--》realm 域中的認證方法
        subject.login(token);
       //登錄之后完成授權 ,是否具有某個角色
        System.out.println(subject.hasRole("admin")); //是否有admin 這個角色
        System.out.println(subject.hasRole("root")); //是否有root 這個角色
        System.out.println(subject.isPermitted("user:save"));// 是否有 user:save 這個權限
    }
    
}
View Code

參考視頻 :https://www.bilibili.com/video/av75572951?p=108


免責聲明!

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



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