通讀本文帶你掌握Shiro安全認證框架

shiro依賴  shiro-all 及 thymeleaf-extras-shiro


 ShiroConfig配置類

package com.qust.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.mgt.SecurityManager;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;

import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;

import java.util.HashMap;

import java.util.Map;

/**
 * springboot支持註解注入bean,往往用於springboot不集成的第三方組件
 *
 */
@Configuration
public class ShiroConfiguration {
    /**
     * 配置攔截器 請求認證權限 都是靠攔截器
     * @param securityManager
     * @return
     */
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean getShiroFilter(SecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //登錄的url
        shiroFilterFactoryBean.setLoginUrl("/loginPage");
        //成功後的請求
        shiroFilterFactoryBean.setSuccessUrl("/index");
        //未授權頁面
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauth");
        //過濾器
        Map<String,String> map = new HashMap<>();
        map.put("/loginPage","anon");
        map.put("/login","anon");
        //anon 無需認證
        map.put("/register","anon");
        //authc 必須要認證
        map.put("/**","authc");
        map.put("/addUser","roles[role1]");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }

    /**
     * 配置SecurityManager
     * @param myRealm
     * @return
     */
    @Bean(name = "securityManager")
    public SecurityManager getSecurityManager(MyRealm myRealm){
        SecurityManager securityManager = new DefaultWebSecurityManager(myRealm);
        return securityManager;
    }

    /**
     * 創建自定義realm
     * @return
     */
    @Bean(name = "myRealm")
    public MyRealm getMyRealm(){
        return new MyRealm();
    }

    /**
     * 配置shiro和thymelf進行整合
     * @return
     */
    @Bean
    public ShiroDialect shiroDialect(){
        return new ShiroDialect();
    }
}

 

 自定義MyRealm

package com.qust.config;

import com.qust.entity.Role;
import com.qust.service.TeacherService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.Permission;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

public class MyRealm extends AuthorizingRealm {

    @Autowired
    private TeacherService teacherService;

    public TeacherService getTeacherService() {
        return teacherService;
    }

    public void setTeacherService(TeacherService teacherService) {
        this.teacherService = teacherService;
    }

    /**
     * 授權
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //只有通過認證後 纔可以考慮授權的問題    獲取到認證後返回的信息
        SimpleAuthorizationInfo sai = new SimpleAuthorizationInfo();
        //獲取用戶名
        String username = getAvailablePrincipal(principalCollection).toString();
        //通過用戶名 獲取該用戶有的角色
        List<Role> roles = teacherService.getRoleByName(username);
        for (Role role1 : roles) {
            sai.addRole(role1.getRname());
        }
        //通過用戶名獲取擁有的權限
        List<Permission> permission = userService.getPermissionByName(username);
        for (Permission permission1 : permission) {
            sai.addStringPermission(permission1.getPname());
        }
        return sai;
    }

    /**
     * 認證
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //獲取令牌
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        //username是肯定相同的 比較密碼
        String account = teacherService.queryPwdByName(token.getUsername());
        if(account != null){
            //三個參數(用戶名、密碼、本realm名字)
            return new SimpleAuthenticationInfo(token.getUsername(),account,getName());
        }
        return null;
    }
}

 

Controller層

@PostMapping("/login")
    public String login(String username, String password, Model model){
        String pass = new Md5Hash(password).toString();
        //創建令牌 將前端傳過來的用戶名、密碼放進令牌
        UsernamePasswordToken token = new UsernamePasswordToken(username,pass);
        try {
            //通過SecurityUtils 獲取用戶主體
            Subject subject = SecurityUtils.getSubject();
            //將登錄交給SecurityManager進行管理
            subject.login(token);
            //將信息存入session
            // subject.getSession().setAttribute("account",account);
            //判斷登錄的主體是否有user角色
            boolean user = subject.hasRole("user");
            //判斷登錄的主題是否有該權限
            boolean add = subject.isPermitted("add");
            return "index";
        } catch (UnknownAccountException e) {
            model.addAttribute("msg","用戶名錯誤");
            return "login";
        } catch (IncorrectCredentialsException e) {
            model.addAttribute("msg", "密碼錯誤");
            return "login";
        }
    }

認證流程圖  


授權流程圖 

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