1. 程式人生 > >Spring 整合Shiro:記住我

Spring 整合Shiro:記住我

有限公司 remember post 是否 RKE term set lock dag

1、登錄方法

/**
     * 執行登錄操作
     *
     * @param username
     * @param password
     * @param rememberMe
     * @param model
     * @return
     */
    @Log("登錄")
    @RequestMapping("/login")
    String login(String username, String password, Boolean rememberMe, Model model) {
        
//判斷用戶名和密碼為空 if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) { model.addAttribute("msg", "用戶名和密碼不能為空!"); return "login.html"; } // shiro登錄步驟 // 1、獲取subject對象 Subject subject = SecurityUtils.getSubject();
// 2、封裝對象 UsernamePasswordToken token = new UsernamePasswordToken(username, password); System.out.println(token.toString()); // 3、執行登錄(失敗會報異常,需捕獲異常) // 實際開發中,用戶名和密碼錯誤,不給出明確提示 try { // 設置是否記住我 rememberMe = rememberMe == null ? false : rememberMe;
// 設置記住我 token.setRememberMe(rememberMe);
       // 登錄 subject.login(token);
// 這樣url會改變為index_v1,不然還會是login return "redirect:/index_v1"; } catch (UnknownAccountException e) {//賬號不存在 model.addAttribute("msg", "用戶名不存在!"); return "/login"; } catch (LockedAccountException e) {//賬戶鎖定 model.addAttribute("msg", "賬戶被鎖定!"); return "/login"; } catch (IncorrectCredentialsException e) {//密碼錯誤 model.addAttribute("msg", "密碼錯誤!"); return "/login"; } }

2、ShiroConfig

/**
 * Copyright (C), 2018-2018, 謫仙科技有限公司
 * FileName ShiroConfig
 * Author wangzhiguo
 * Date 2018-12-25 2:49
 * Description Shiro配置
 * History
 * <author>          <time>          <version>          <desc>
 * wangzhiguo        2018-12-25          版本號              描述
 */
package com.itgeek.config.shiro.config;

import com.itgeek.config.shiro.realm.Myrealm;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 〈功能描述〉
 * Shiro配置
 * <p>
 * <p>
 * 系統啟動,執行順序
 * realm -- > securityManager -- > filter
 *
 * @author wangzhiguo
 * @date 2018-12-25
 * @since 1.0.0
 */

@Configuration
public class ShiroConfig {
    /**
     * shiro核心filter
     *
     * @return
     */
    @Bean()
    public ShiroFilterFactoryBean getShiroFilterFactoryBean() {
        System.out.println("Shiro過濾器");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 設置SecurityManager(必須)
        shiroFilterFactoryBean.setSecurityManager(securityManager());
        /**
         * shiro常用過濾器
         * anon:無需認證
         * authc:必須認證
         * user:如果使用rememberMe功能可以直接訪問
         * perms:必須得到資源權限可以訪問
         * role:必須得到角色權限可以訪問
         */
        // LinkedHashMap 可以保持順序
        Map<String, String> filterMap = new LinkedHashMap<>();

        // 1、認證
        filterMap.put("/", "anon");
        filterMap.put("/index", "anon");

        filterMap.put("/toLogin", "anon");
        filterMap.put("/login", "anon");

        // 2、資源權限
        filterMap.put("/sys/add", "perms[user:edit]");
        // 3、角色權限

        // 所有請求都要認證
        // filterMap.put("/**", "authc");
        // 認證或記住我都可以登錄
        filterMap.put("/**", "user");
        // 未授權
        shiroFilterFactoryBean.setUnauthorizedUrl("/noAuth");
        // 設置跳轉的登錄頁
        shiroFilterFactoryBean.setLoginUrl("/toLogin");
        // 設置登錄成功的頁面
        shiroFilterFactoryBean.setSuccessUrl("/index_v1");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactoryBean;
    }

    /**
     * 安全管理器
     * 緩存註入在這
     *
     * @return
     */
    @Bean()
    public DefaultWebSecurityManager securityManager() {
        System.out.println("Shiro安全管理器");
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 設置realm
        securityManager.setRealm(myrealm());
        // session會話
        // securityManager.setSessionManager(sessionManager());
        // 設置記住我
        securityManager.setRememberMeManager(rememberMeManager());
        return securityManager;
    }

    /**
     * realm:自定義的認證和授權邏輯
     *
     * @return
     */
    @Bean()
    public Myrealm myrealm() {
        System.out.println("自定義Realm");
        return new Myrealm();
    }

    /**
     * 記住我
     *
     * @return
     */
    @Bean
    public CookieRememberMeManager rememberMeManager() {
        System.out.println("記住我:rememberMe");
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookie());
        //這個地方有點坑,不是所有的base64編碼都可以用,長度過大過小都不行,沒搞明白,官網給出的要麽0x開頭十六進制,要麽base64
        cookieRememberMeManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));
        return cookieRememberMeManager;
    }

    /**
     * Cookie管理
     * 創建記住我cookie
     *
     * @return
     */
    @Bean
    public SimpleCookie rememberMeCookie() {
        System.out.println("rememberMeCookie");
        SimpleCookie cookie = new SimpleCookie("rememberMe");
        cookie.setHttpOnly(true);
        // 聲明周期
        cookie.setMaxAge(1 * 60 * 60);
        return cookie;
    }
}

3、登錄頁面

<form action="/login" method="post">
        <span style="color: red" th:text="${msg}"></span>
        <br>
        姓名<input type="text" name="username"> <br>
        密碼<input type="password" name="password"> <br>
        記住我<input type="checkbox" checked="checked" name="rememberMe"> <br>
        <button type="submit">登錄</button>
    </form>
技術分享圖片

4、登錄(記住我),會生成rememberMe CookIe

技術分享圖片

不記住我:rememberMe Cookie 不會生成

技術分享圖片

註銷(SHiro:/logout)也會清除rememberMe Cookie

Spring 整合Shiro:記住我