Shrio04 自定義Realm

1 說明

1.1 Realm的做用

Realm和認證和受權時的數據交互有關,至關於DAO層。前端

1.2 AuthorizingRealm

》層次關係圖
java

》做用
繼承AuthorizingRealm類後重寫doGetAuthorizationInfo和doGetAuthenticationInfo就能夠實現受權和認證邏輯。apache

2 代碼實現

2.1 建立一個maven項目並引入shiro、junit依賴

2.2 建立一個類繼承AuthorizingRealm

2.3 重寫doGetAuthorizationInfo和doGetAuthenticationInfo

2.4 完整代碼

package com.xunyji.demo04.realm;

import com.xunyji.demo0.StringUtilsXyj;
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.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @author AltEnter
 * @create 2019-01-23 20:32
 * @desc 自定義Realm,md
 **/
public class CustomRealm extends AuthorizingRealm {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    private Map<String, String> userMap = new HashMap<String, String>();

    {
        getName();
//        userMap.put("fury", "111111");
//        userMap.put("fury", "96e79218965eb72c92a549dd5a330112");
        userMap.put("fury", "66b747dd6c7c7c8ca4227a67fff8ea6e");
    }

    /**
     * 受權邏輯
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // 01 獲取用戶名
        String username = (String) principals.getPrimaryPrincipal();
        // 02 獲取權限集合
        Set<String> permissionSet = getPermissionSetByUsername(username);
        // 03 獲取角色集合
        Set<String> roleSet = getRoleSetByUsername(username);
        // 04 封裝SimpleAuthorizationInfo對象
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.setRoles(roleSet);
        simpleAuthorizationInfo.setStringPermissions(permissionSet);
        return simpleAuthorizationInfo;
    }

    /**
     * 根據用戶名獲取權限集合
     * @param username
     * @return
     */
    private Set<String> getPermissionSetByUsername(String username) {
        HashSet<String> permissionSet = new HashSet<>();
        permissionSet.add("user:create");
        permissionSet.add("user:delete");
        permissionSet.add("user:update");
        return permissionSet;
    }

    /**
     * 根據用戶名獲取角色集合
     * @param username
     * @return
     */
    private Set<String> getRoleSetByUsername(String username) {
        HashSet<String> roleSet = new HashSet<>();
        roleSet.add("admin");
        roleSet.add("user");
        return roleSet;
    }

    /**
     * 認證邏輯
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 01 獲取前端用戶名和密碼
        String username = (String) token.getPrincipal();
        String passoword = new String((char[]) token.getCredentials());
        if (StringUtilsXyj.isEmpty(passoword) || StringUtilsXyj.isEmpty(username)) {
            String msg = "doGetAuthenticationInfo - 用戶名和密碼不能爲空";
            log.info(msg);
            throw new RuntimeException(msg);
        }
        log.info(String.format("doGetAuthenticationInfo - 前端傳過來的用戶信息爲 - 用戶名爲:%s ,用戶密碼爲:%s", username, passoword));
        System.out.println(String.format("doGetAuthenticationInfo - 前端傳過來的用戶信息爲 - 用戶名爲:%s ,用戶密碼爲:%s", username, passoword));

        // 02 根據用戶名獲取用戶密碼
        String pwd = getPasswordByUsername(username);
        // 03 前端密碼加密加鹽處理
        passoword = string2Md5Hash(passoword, "AltEnter");
        System.out.println("加鹽加密後的密碼爲:" + pwd);

        // 04 密碼比對
        if (passoword.equals(pwd)) {
            // 封裝SimpleAuthenticationInfo對象
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, passoword, getName());
            // 加鹽處理
            simpleAuthenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("AltEnter"));
            return simpleAuthenticationInfo;
        } else {
            String msg = "doGetAuthenticationInfo - 用戶名或者密碼錯誤";
            log.info(msg);
            System.out.println(msg);
            throw new RuntimeException(msg);
        }
    }

    /**
     * 密碼加密加鹽處理
     * @param password 待加密密碼
     * @param salt 鹽
     * @return 通過加密和加鹽處理後的密碼
     */
    private String string2Md5Hash(String password, String salt) {
        return new Md5Hash(password, salt).toString();
    }

    /**
     * 根據用戶名獲取密碼
     * @param username
     * @return
     */
    private String getPasswordByUsername(String username) {
        String pwd = userMap.get(username);
        return pwd;
    }

    public static void main(String[] args) {
//        Md5Hash md5Hash = new Md5Hash("111111");
//        System.out.println("111111加密後的結果爲:" + md5Hash.toString());
//        96e79218965eb72c92a549dd5a330112

        Md5Hash md5Hash = new Md5Hash("111111", "AltEnter");
        System.out.println("111111通過MD5加密和AltEnter加鹽後的結果爲:" + md5Hash.toString());
//        66b747dd6c7c7c8ca4227a67fff8ea6e
    }
}

3 測試類

package com.xunyji.demo04.realm;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authc.pam.FirstSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.junit.Test;

import static org.junit.Assert.*;

public class CustomRealmTest {
    @Test
    public void test01() {
        CustomRealm customRealm = new CustomRealm();
        // shiro加密 start
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        //選擇加密方式
        matcher.setHashAlgorithmName("md5");
        //加密次數
        matcher.setHashIterations(1);
        // 給自定義Realm設置加密規則
        customRealm.setCredentialsMatcher(matcher);
//        shiro加密 end

        // 更改認證策略 start
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        FirstSuccessfulStrategy firstSuccessfulStrategy = new FirstSuccessfulStrategy();
        ModularRealmAuthenticator modularRealmAuthenticator = new ModularRealmAuthenticator();
        modularRealmAuthenticator.setAuthenticationStrategy(firstSuccessfulStrategy);
        defaultSecurityManager.setAuthenticator(modularRealmAuthenticator);
        // 更改認證策略 end

        defaultSecurityManager.setRealm(customRealm);

        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken token = new UsernamePasswordToken("fury", "111111");

        subject.login(token);
        System.out.println(String.format("認證信息爲:%s", subject.isAuthenticated()));

        System.out.println(String.format("擁有admin角色嗎? - %s", subject.hasRole("admin")));
        System.out.println(String.format("擁有user:create權限嗎? - %s", subject.isPermitted("user:create")));

        subject.logout();
        System.out.println(String.format("認證信息爲:%s", subject.isAuthenticated()));


    }
}

4 注意

4.1 能夠給SecurityManager設置認證策略

4.2 能夠給Realm設置MD5加密

4.3 SecurityManager必須先設置認證策略再設置Realm

 

相關文章
相關標籤/搜索