SpringBoot整合Shiro實現賬號密碼登錄


shiro安全框架簡介

Apache Shiro是一個強大且易用的Java安全框架,執行身份驗證、授權、密碼和會話管理。

三個核心組件:Subject, SecurityManager 和 Realms.

  • Subject:代表了當前用戶的安全操作,SecurityManager則管理所有用戶的安全操作。
  • SecurityManager:它是Shiro框架的核心,Shiro通過SecurityManager來管理內部組件實例,並通過它來提供安全管理的各種服務。
  • Realm: Realm充當了Shiro與應用安全數據間的“橋梁”或者“連接器”。當對用戶執行認證(登錄)和授權(訪問控制)驗證時,Shiro會從應用配置的Realm中查找用戶及其權限信息。Realm實質上是一個安全相關的DAO:它封裝了數據源的連接細節,並在需要時將相關數據提供給Shiro。當配置Shiro時,你必須至少指定一個Realm,用於認證和(或)授權。
  • 導入依賴(pom.xml) 

        <!--整合Shiro安全框架-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>
        <!--集成jwt實現token認證-->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.2.0</version>
        </dependency>
  • 創建 ShiroConfig 配置類

@Configuration
public class ShiroConfig {

    /**
     * ShiroFilterFactoryBean
     */
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        //設置安全管理器
        factoryBean.setSecurityManager(defaultWebSecurityManager);
        // 添加shiro的內置過濾器
        /*
         *  anon:無需認證就可以訪問
         *  authc:必須認證才能訪問
         *  user:必須擁有 記住我 功能才能用
         *  perms:擁有對某個資源的權限能訪問
         *  role:擁有某個角色權限能訪問
         */
        Map<String, String> filterMap = new LinkedHashMap<>();
        // 放行不需要權限認證的接口
        //放行登錄接口
        filterMap.put("/login/**", "anon");
        //放行用戶接口
        filterMap.put("/", "anon");             // 網站首頁
  
        //認證管理員接口
        filterMap.put("/administrators/**", "authc");
        factoryBean.setFilterChainDefinitionMap(filterMap);
        // 設置無權限時跳轉的 url
        // 設置登錄的請求
        factoryBean.setLoginUrl("/login/toLogin");

        return factoryBean;
    }

    /**
     * 注入 DefaultWebSecurityManager
     */
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("customRealm") CustomRealm customRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //關聯CustomRealm
        securityManager.setRealm(customRealm);
        return securityManager;
    }

    /**
     * 注入 securityManager
     */
    @Bean
    public CustomRealm customRealm() {
        return new CustomRealm();
    }

}
  • 創建密碼登錄時驗證授權 CustomRealm 類

@Component
public class CustomRealm extends AuthorizingRealm {

    @Autowired
    AdministratorsService administratorsService;

    /*
     * 設置加密方式
     */
    {
        HashedCredentialsMatcher mather = new HashedCredentialsMatcher();
        // 加密方式
        mather.setHashAlgorithmName("md5");
        // 密碼進行一次運算
        mather.setHashIterations(512);
        this.setCredentialsMatcher(mather);
    }

    /**
     * 授權
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("————授權————doGetAuthorizationInfo————");

        return null;
    }

    /**
     * 認證
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("————認證————doGetAuthenticationInfo————");

        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
        // 連接數據庫  查詢用戶數據
        QueryWrapper<Administrators> wrapper = new QueryWrapper<>();
        wrapper.eq("username", userToken.getUsername());
        Administrators administrators = administratorsService.getOne(wrapper);

        if (administrators == null) {
            return null;  // 拋出異常 UnknownAccountException
        }
        // 密碼認證,shiro做
        return new SimpleAuthenticationInfo("", administrators.getPassword(), "");
    }

}
  • 控制層用戶密碼登錄

//用戶名登錄
    @ApiOperation(value = "管理員登錄", notes = "用戶名登錄--不進行攔截")
    @PostMapping("/doLogin")
    public String doLogin(@RequestParam("username") String username,
                          @RequestParam("password") String password,
                          HttpSession session,Model model) {
        // 獲取當前的用戶
        Subject subject = SecurityUtils.getSubject();
        // 封裝用戶的登錄數據
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        try {
            subject.login(token);
            //保存session會話 管理員名字
            session.setAttribute("adname", username);
            return "admin";
        } catch (UnknownAccountException e) {
            model.addAttribute("usererror", "用戶名錯誤!請重新輸入。");
            return "login";
        } catch (IncorrectCredentialsException ice) {
            model.addAttribute("pwerror", "密碼錯誤!請重新輸入。");
            return "login";
        }
    }


免責聲明!

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



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