shiro登錄過程

工作流程:

瀏覽器將用戶名、密碼、是否記住登錄等信息發送給登錄controller ,

new UsernamePasswordToken()獲取token,將用戶名、加密後的密碼、rememberMe,set到token中。SecurityUtils.getSubject();獲取subject對象,執行subect.login(token)進行登錄操作並捕獲可能出現的賬號密碼錯誤等異常。

 

1.前端登錄頁面將用戶名、密碼、是否記住登錄,傳入到Controller

Controller登錄方法:

//1.獲取shiro中的subject對象
Subject subject = SecurityUtils.getSubject();
//2.對用戶從頁面輸入的密碼進行加密處理
password = new Md5Hash(password,username,1024).toString();
System.out.println("加密後的密碼: " + password);
//3.創建shiro中的用戶名和密碼對象,將用戶輸入的用戶名密碼交給shiro管理
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
//4.關於記住我的設置
System.out.println("是否記住我: " + rememberMe);
if(rememberMe){
    token.setRememberMe(true);
}
//5.調用shiro的登錄方法,調用後,shiro會自動執行Realm實現類===========
try {
    subject.login(token);
    System.out.println("開始登陸");
} catch (UnknownAccountException e) {
    return new Result(1, "賬號不存在");
}catch (IncorrectCredentialsException e){
    return new Result(1,"密碼錯誤");
}catch (AuthenticationException e){
    System.out.println("其他異常");
    return new Result(1,"其他異常");
}
return new Result(0, "登陸成功!");

/**
 * 註銷方法
 * @return
 */
public Result logout(){
    //1.獲取subject對象
    Subject subject =  SecurityUtils.getSubject();
    //2.返回註銷方法
    subject.logout();
    //3.返回
    return Result.ok("註銷成功");
}

獲取完數據後,shiro會自動執行Realm的實現類,實現類需要手動實現,如下:

/**
 * projectName: myproject
 * @author: xxx
 * time: 2021/9/6 21:17
 * description:  自定義realm對象
 *
 *  1.從數據庫根據用戶名,取出數據庫中的用戶名,密碼交給shiro框架
 *  2.根據用戶名,到數據庫取出用戶對應的角色和權限對象交給shiro框架管理
 */

public class MyUserRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;
    @Autowired
    private MenuService menuService;
    @Autowired
    private RoleService roleService;

    /**
     *     用戶輸入的用戶名和密碼輸入正確,校驗完成後進行賦值操作
     *     根據用戶名到數據庫查詢這個用戶對應的角色和權限,交給shiro管理
     *     調用時機:在需要訪問資源的時候,需要角色和權限的視乎纔會調用此方法
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        System.out.println("已登陸成功,授予登錄用戶權限,也就是賦予用戶對應的角色和能夠訪問的菜單");

        //1.獲取當前登錄的用戶對象
        SysUsers sysUSers = (SysUsers) principalCollection.getPrimaryPrincipal();

        //2.獲取當前登錄用戶的 用戶id
        int uid = sysUSers.getId();

        //3.根據用戶id,查詢數據庫中這個用戶對應的角色集合和權限集合
        Set<String> roleList = roleService.findRoleListByUid(uid);
        Set<String> menuList = menuService.findMenuListbyUid(uid);

        //4.創建shiro中的用戶權限對象
        SimpleAuthorizationInfo auth = new SimpleAuthorizationInfo();

        //5.將查詢到的角色集合放入shiro的權限對象
        auth.setRoles(roleList);

        //6.將查詢到的權限集合放入shiro的權限對象
        auth.setStringPermissions(menuList);

        //7.返回shiro權限對象
        return auth;
    }

    /**
     *     根據用戶在頁面輸入的用戶名,查詢數據庫中的用戶名和密碼,交給shiro框架
     *     讓shiro框架進行對比用戶名,密碼是否正確
     *    調用時機:在controller調用subject.login(token);方法就會執行這個方法,進行用戶名 密碼校驗
     * @param auth
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
        System.out.println("開始校驗用戶名和密碼................");

        //1.獲取用戶在瀏覽器輸入的用戶名
        String userName = (String) auth.getPrincipal();
        //2.根據用戶輸入的用戶名,查詢數據庫的用戶對象
        String password = new String((char[]) auth.getCredentials());
        //3.判斷用戶是否爲空,爲空則拋出異常
        SysUsers sysUSer = userService.findUserbyName(userName);
        if (sysUSer == null) {
            throw new UnknownAccountException("賬號不存在,請先註冊,再登錄!");
        }
        //4.對比數據庫的密碼和用戶輸入的密碼是否一致
        if(!password.equals(sysUSer.getPassword())){
            throw new IncorrectCredentialsException("密碼錯誤");
        }
        //5.判斷用戶狀態,1正常,其他爲鎖定狀態
        if(sysUSer.getStatus() != 1){
            throw new LockedAccountException("賬號被鎖定不允許登錄");
        }
        //6.封裝shiro中需要的權限對象,包括用戶名 密碼 以及當前用戶對象交給shiro返回
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userName, password, this.getName());
        return info;
    }
}

其他Controller方法需要做權限驗證時,可以在上面加註解@RequiresPermissions("sys:product:add")

括號裏是權限字符串,用冒號連接

shiro註解用在Service和Controller層,但是如果Service層有事務註解,那麼shiro註解要放在Controller層。因爲兩個代理對象在類型轉換時會出現異常。

https://www.cnblogs.com/huangruiwu/p/15410382.html

 

 

 

2、接口獲取用戶名,密碼生成UsernamePasswordToken並提交認證:

@Controller
@RequestMapping("/api")
public class ApiController {
 
    @Autowired
    SysMenuService sysMenuService;
 
    @RequestMapping("/login")
    @ResponseBody
    public ResponseVO login(String username, String password) {
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        //獲取當前的Subject
        Subject currentUser = SecurityUtils.getSubject();
        try {
            // 在調用了login方法後,SecurityManager會收到AuthenticationToken,並將其發送給已配置的Realm執行必須的認證檢查
            // 每個Realm都能在必要時對提交的AuthenticationTokens作出反應
            // 所以這一步在調用login(token)方法時,它會走到xxRealm.doGetAuthenticationInfo()方法中,具體驗證方式詳見此方法
            currentUser.login(token);
 
            //認證通過,將菜單信息返回給前端展示
            if (currentUser.isAuthenticated()) {
                MenuSystem menuSystem = sysMenuService.findMenuTree();
                Gson gson = new Gson();
                String menuJson = gson.toJson(menuSystem, MenuSystem.class);
                return ResultUtil.success("登錄成功!", menuJson);
            }
        } catch (UnknownAccountException e1) {
            e1.printStackTrace();
            return ResultUtil.error("用戶名不存在!");
        } catch (IncorrectCredentialsException e2) {
            e2.printStackTrace();
            return ResultUtil.error("密碼輸入錯誤!");
        } catch (Exception e) {
            e.printStackTrace();
            return ResultUtil.error(e.getMessage());
        }
        return ResultUtil.error("登錄失敗!");
    }

說明:這裏的菜單數據並沒有使用shiro標籤來實現,因爲layuimini的菜單渲染是通過json數據的形式來實現的,所以這裏我也是將菜單數據轉換成了json給前端。

如果認證通過,那麼通過subject.isAuthenticated()返回的結果就會是true,我們就可以認爲登錄成功了,此時,可以就可以將對應的菜單信息傳回給前端渲染展示了。

https://blog.csdn.net/superyu1992/article/details/125915866

https://blog.csdn.net/superyu1992/article/details/126014248

https://blog.csdn.net/superyu1992/article/details/126058351

 

https://blog.51cto.com/wyait/2082803

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章