Shiro-01-登錄

Shiro的登錄

以下代碼是一段簡單的shiro登錄代碼

	@RequestMapping(value = "/subLogin",method = RequestMethod.POST)
    @ResponseBody
    public String subLogin(SubLoginForm subLoginForm){
        Subject subject = SecurityUtils.getSubject();
        if(subject.isAuthenticated()){
            System.out.println("已經登錄,無需再次登錄");
            return "redirect:index.html";
        }
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(subLoginForm.getUsername(),subLoginForm.getPassword());
        try{
            if(subLoginForm.getRememberMe() != null){
                usernamePasswordToken.setRememberMe(subLoginForm.getRememberMe());
            }
            subject.login(usernamePasswordToken);
        }catch (AuthenticationException e){
            e.printStackTrace();
        }
        if(subject.hasRole("admin")){
            return "有admin權限";
        }
        return "無admin權限";
    }

在這一段代碼中,我要分析一下subject.login(usernamePasswordToken);這一步

以下是個人現階段的見解,如有不正確請指出!

任意一個系統,集成shiro的時候,關於用戶,角色,權限等,基本都會用自定義表結構,所以我們需要自定義realm,來和數據庫交互。如圖所示:

在這裏插入圖片描述
在realm中,從自定義的用戶表中,查詢出來用戶信息,用來校驗用戶本次是否登錄成功。

以下代碼是一個自定義的realm

package com.imooc.shiro.realm;

import cn.hutool.core.collection.CollUtil;
import com.imooc.dao.UserDao;
import com.imooc.vo.User;
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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.Set;

/**
 * @author jianxinkuan
 * @date 2020/3/15 18:53
 */
public class CustomRealm extends AuthorizingRealm {

    @Resource
    private UserDao userDao;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //1、獲取登錄用戶名
        String userName = (String) principalCollection.getPrimaryPrincipal();
        //2、通過用戶名獲取角色
        Set<String> roleSet = getRolesByUserName(userName);
        //3、根據用戶名獲取權限
        Set<String> permissionSet = getPermissionsByUserName(userName);
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        //設置角色
        simpleAuthorizationInfo.setRoles(roleSet);
        //設置權限
        simpleAuthorizationInfo.setStringPermissions(permissionSet);
        return simpleAuthorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //1、從認證主體中獲取用戶名
        String userName = (String) authenticationToken.getPrincipal();
        //2、通過用戶名從數據庫庫中檢索用戶
        User user = getPasswordByUserName(userName);
        if(user == null){
            return null;
        }
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userName, user.getPassword(), "admin");
        //可以在這裏加鹽值
//        simpleAuthenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("JXK"));
        return simpleAuthenticationInfo;
    }


    /**
     * 根據用戶名獲取權限
     * @param userName
     */
    private Set<String> getPermissionsByUserName(String userName) {
        System.out.println("從數據庫獲取權限信息");
        userDao.queryRolesByUserName(userName);
        Set<String> permissionSet = new HashSet<>();
        permissionSet.add("user:add");
        permissionSet.add("user:delete");
        permissionSet.add("user:update");
        permissionSet.add("user:list");
        return permissionSet;
    }

    /**
     * 根據用戶名獲取角色
     * @param userName
     * @return
     */
    private Set<String> getRolesByUserName(String userName) {
        System.out.println("從數據庫獲取角色信息");
        return CollUtil.newHashSet(userDao.queryRolesByUserName(userName));
    }


    /**
     * 數據庫中檢索用戶信息
     * @param userName
     * @return
     */
    private User getPasswordByUserName(String userName) {
        return userDao.getUserByUserName(userName);
    }
}


如代碼所示,自定義realm,我們需要繼承AuthorizingRealm 類,重新兩個方法

  1. doGetAuthorizationInfo
    此方法內實現授權邏輯,我們要從我們自己的角色表,權限表中獲取數據,組裝起來,這樣當前的subject就有了這些角色、權限信息
  2. doGetAuthenticationInfo
    此方內實現認證邏輯,根據用戶名從自定義用戶表中檢索出來用戶,然後把用戶名和密碼返回,這裏我們不用自己去對比密碼是否一致,而判斷用戶是否登錄成功,shiro框架會自行判斷,這裏我們還可以設置加密規則的鹽值信息
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章