欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

springboot整合shiro實(shí)現(xiàn)記住我功能

 更新時間:2021年10月26日 09:38:02   作者:桐花思雨  
這篇文章主要介紹了springboot整合shiro實(shí)現(xiàn)記住我功能,配置類 ShiroConfig,通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下

前言

上一篇 文章我們完成了在 thymeleaf 模板引擎中使用 shiro 標(biāo)簽,也就是根據(jù)不同的用戶身份信息,前端頁面來顯示不同的頁面內(nèi)容。本篇文章我們來完成在登錄頁面的記住我的功能

springboot 整合 shiro 之實(shí)現(xiàn)記住我

項目依然使用 springboot整合shiro 這個項目,稍稍改動即可完成記住我的功能

配置類 ShiroConfig

完整的代碼如下

@Configuration
public class ShiroConfig {

    /**
     * 安全管理器
     *
     * @param userRealm userRealm
     * @return defaultWebSecurityManager
     */
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(UserRealm userRealm) {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(userRealm);
        // 實(shí)現(xiàn)記住我,所需要的配置
        defaultWebSecurityManager.setRememberMeManager(cookieRememberMeManager());
        return defaultWebSecurityManager;
    }

    /**
     * thymeleaf模板引擎中使用shiro標(biāo)簽時,要用到
     *
     * @return
     */
    @Bean
    public ShiroDialect getShiroDialect() {
        return new ShiroDialect();
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager defaultWebSecurityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        // 設(shè)置登錄頁面url
        shiroFilterFactoryBean.setLoginUrl("/user/login");
        shiroFilterFactoryBean.setSuccessUrl("/user/index");
        shiroFilterFactoryBean.setUnauthorizedUrl("/user/unauthorized");

        // 注意此處使用的是LinkedHashMap是有順序的,shiro會按從上到下的順序匹配驗證,匹配了就不再繼續(xù)驗證
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();

        filterChainDefinitionMap.put("/layer/**", "anon");// 靜態(tài)資源放行
        filterChainDefinitionMap.put("/img/**", "anon");
        filterChainDefinitionMap.put("/jquery/**", "anon");
        // add.html頁面放行
        filterChainDefinitionMap.put("/user/add", "authc");
        // update.html必須認(rèn)證
        filterChainDefinitionMap.put("/user/update", "authc");
        // index.html必須認(rèn)證
        filterChainDefinitionMap.put("/user/index", "user");
        // 設(shè)置授權(quán),只有user:add權(quán)限的才能請求/user/add這個url
        filterChainDefinitionMap.put("/user/add", "perms[user:add]");
        filterChainDefinitionMap.put("/user/update", "perms[user:update]");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

	// 實(shí)現(xiàn)記住我,所需要的配置
    @Bean
    public SimpleCookie simpleCookie() {
        // 這個參數(shù)是cookie的名稱,對應(yīng)前端的checkbox的name = rememberMe
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        simpleCookie.setHttpOnly(true);
        // 記住我cookie生效時間1小時,單位秒
        simpleCookie.setMaxAge(60 * 60);
        return simpleCookie;
    }

	// 實(shí)現(xiàn)記住我,所需要的配置
    @Bean
    public CookieRememberMeManager cookieRememberMeManager() {
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(simpleCookie());
        // rememberMe cookie加密的密鑰 建議每個項目都不一樣 默認(rèn)AES算法 密鑰長度(128 256 512 位)
        cookieRememberMeManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));
        return cookieRememberMeManager;
    }
}

login.html 登錄頁面

此時要拿到復(fù)選框 checkbox 是否被用戶選中的狀態(tài)值,選中為 true,未選中為 false,將這個狀態(tài)值發(fā)生至后端登錄接口

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>登錄</title>
    <link rel="shortcut icon" type="image/x-icon" th:href="@{/img/favicon.ico}"/>
</head>
<body>
<form action="" method="post">
    <p>
        賬號:
        <label><input type="text" class="username" name="username"></label>
    </p>
    <p>
        密碼:
        <label><input type="text" class="password" name="password"></label>
    </p>
    <p>
        <label><input id="checkbox1" type="checkbox" name="rememberMe"></label>記住我
    </p>
    <p><button type="button" class="loginBtn">登錄</button></p>
</form>
</body>
<script type="text/javascript" th:src="@{/jquery/jquery-3.3.1.min.js}"></script>
<script type="text/javascript" th:src="@{/layer/layer.js}"></script><!--layui的彈出層-->
<script type="text/javascript">
    $(document).ready(function () {
        $('.loginBtn').on('click', function () { // 登錄按鈕
            const username = $('.username').val();
            const password = $('.password').val();
            const rememberMe = $("input[type='checkbox']").is(':checked');
            $.ajax({// 用戶登錄
                type: 'post',
                url: '/user/doLogin',
                dataType: 'json',
                data: ({
                    'username': username,
                    'password': password,
                    'rememberMe': rememberMe
                }),
                success: function (resp) {
                    console.log(resp);
                    if (resp.code !== 200) {
                        layer.msg(resp.message, function () {// layui的彈窗
                        });
                    } else if (resp.code === 200) {
                        window.location.+ resp.action;
                    }
                },
                error: function () {// 此處添加錯誤處理
                    layer.open({
                        title: '提示信息',
                        content: '后臺訪問錯誤,請聯(lián)系管理員',
                        skin: 'layui-layer-molv',
                        icon: 0
                    });
                }
            });
        });
    });
</script>
</html>

controller

@Controller
@RequestMapping(path = "/user")
@Slf4j
public class UserController {

    @GetMapping(path = "/login")
    public String login() {
        return "login";
    }

    @GetMapping(path = "/index")
    public String index() {
        return "index";
    }

    @GetMapping(path = "/add")
    public String add() {
        return "add";
    }

    @GetMapping(path = "/update")
    public String update() {
        return "update";
    }

    @GetMapping(path = "/unauthorized")
    public String unauthorized() {
        return "unauthorized";
    }

    /**
     * 用戶登錄
     *
     * @param userVO
     * @param bindingResult
     * @return
     */
    @PostMapping(path = "/doLogin")
    @ResponseBody
    public ResultMap doLogin(@NotNull @Valid UserVO userVO, @NotNull BindingResult bindingResult) {
        // ------參數(shù)校驗------
        if (bindingResult.hasErrors()) {
            String message = Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage();
            log.info("校驗的message信息為:" + message);
            return new ResultMap().fail().message(message);
        }
        // 將用戶名,密碼交給shiro
        UsernamePasswordToken token = new UsernamePasswordToken(userVO.getUsername(), userVO.getPassword(), userVO.getRememberMe());
        String msg;
        try {
            // shiro幫我們匹配密碼什么的,我們只需要把東西傳給它,它會根據(jù)我們在UserRealm里認(rèn)證方法設(shè)置的來驗證
            Subject subject = SecurityUtils.getSubject();
            subject.login(token);
            return new ResultMap().success().action("/user/index");
        } catch (AuthenticationException e) {
            if (e instanceof IncorrectCredentialsException) {
                msg = "密碼錯誤";
            } else if (e instanceof LockedAccountException) {
                msg = "用戶被禁用";
            } else if (e instanceof UnknownAccountException) {
                msg = "用戶不存在";
            } else {
                msg = "用戶認(rèn)證失敗";
            }
        }
        return new ResultMap().error().message(msg);
    }

    /**
     * 用戶退出登錄
     * 添加記住我功能了,退出登錄時,除了要當(dāng)前的subject退出之外,還要刪除用戶瀏覽器上的Cookie信息
     *
     * @return
     */
    @GetMapping(path = "/logout")
    public String logout(HttpServletResponse response) {
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated()) {
            subject.logout();
            Cookie cookie = new Cookie("rememberMe", null);
            cookie.setMaxAge(0);
            response.addCookie(cookie);
        }
        return "login";
    }
}

UserVO

public class UserVO implements Serializable {

    @NotBlank(message = "賬號不能為空")
    private String username;

    @NotEmpty(message = "密碼不能為空")
    private String password;

    private Boolean rememberMe;

	// 省略set/get方法
}

測試

我們以賬號 jack 為例進(jìn)行登錄,如下

在這里插入圖片描述

進(jìn)入首頁頁面如下,再次查看 Cookies 數(shù)據(jù)

在這里插入圖片描述

我們這時關(guān)閉這個首頁頁面,在瀏覽器地址欄輸入 http://127.0.0.1:8080/user/index 再次進(jìn)入首頁頁面,會發(fā)現(xiàn)如上圖一樣,可以順利訪問,說明我們的記住我功能已經(jīng)實(shí)現(xiàn)。這時,可以再次在瀏覽器地址欄輸入 http://127.0.0.1:8080/user/add,進(jìn)入 add.html 頁面,如下

在這里插入圖片描述

Cookies 的有效期內(nèi),當(dāng)你關(guān)閉瀏覽器之后,再次進(jìn)入 add.html 頁面時,無需登錄直接就可以訪問了,說明記住我功能已經(jīng)實(shí)現(xiàn)了。在瀏覽器地址欄輸入 http://127.0.0.1:8080/user/update,進(jìn)入 update.html 頁面,如下

在這里插入圖片描述

說明賬號 jack 沒有權(quán)限訪問 update.html 頁面,可以看控制臺 sql 日志

在這里插入圖片描述

源碼:springboot-shiro

到此這篇關(guān)于springboot整合shiro之實(shí)現(xiàn)記住我的文章就介紹到這了,更多相關(guān)springboot整合shiro之實(shí)現(xiàn)記住我內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring MVC攔截器的基本使用方法

    Spring MVC攔截器的基本使用方法

    這篇文章主要給大家介紹了關(guān)于Spring MVC攔截器的基本使用方法,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Spring MVC具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • Java實(shí)現(xiàn)多文件壓縮打包的方法

    Java實(shí)現(xiàn)多文件壓縮打包的方法

    這篇文章主要介紹了Java實(shí)現(xiàn)多文件壓縮打包的方法,結(jié)合實(shí)例形式分析了java實(shí)現(xiàn)zip文件壓縮與解壓縮相關(guān)操作技巧,需要的朋友可以參考下
    2017-06-06
  • Java語言實(shí)現(xiàn)快速冪取模算法詳解

    Java語言實(shí)現(xiàn)快速冪取模算法詳解

    這篇文章主要介紹了Java語言實(shí)現(xiàn)快速冪取模算法詳解,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • Java struts2 validate用戶登錄校驗功能實(shí)現(xiàn)

    Java struts2 validate用戶登錄校驗功能實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了Java struts2 validate用戶登錄校驗功能實(shí)現(xiàn)的具體步驟,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-05-05
  • Java IO流對文件File操作

    Java IO流對文件File操作

    這篇文章主要介紹了Java IO流對文件File操作,java封裝的一個操作文件及文件夾(目錄)的對象。可以操作磁盤上的任何一個文件和文件夾
    2022-12-12
  • Java8使用Supplier啟動ScheduledThread代碼實(shí)例

    Java8使用Supplier啟動ScheduledThread代碼實(shí)例

    這篇文章主要介紹了Java8使用Supplier啟動ScheduledThread詳解,項目開啟立即啟動定時任務(wù)是很多項目都會遇到的一個需求,如何利用Java提供的函數(shù)優(yōu)雅的寫出來十分考驗一個人的功底,需要的朋友可以參考下
    2024-01-01
  • Kotlin傳遞可變長參數(shù)給Java可變參數(shù)實(shí)例代碼

    Kotlin傳遞可變長參數(shù)給Java可變參數(shù)實(shí)例代碼

    這篇文章主要介紹了Kotlin傳遞可變長參數(shù)給Java可變參數(shù)實(shí)例代碼,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • Spring?@Cacheable注解類內(nèi)部調(diào)用失效的解決方案

    Spring?@Cacheable注解類內(nèi)部調(diào)用失效的解決方案

    這篇文章主要介紹了Spring?@Cacheable注解類內(nèi)部調(diào)用失效的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Java 知識難點(diǎn)之異常的認(rèn)知與使用詳解

    Java 知識難點(diǎn)之異常的認(rèn)知與使用詳解

    所謂異常是指程序在運(yùn)行時出現(xiàn)錯誤時提示調(diào)用者的機(jī)制,異常的種類有很多,不同種類的異常有不同的含義,也有不同的處理方式,通讀本篇對大家的學(xué)習(xí)或工作具有一定的價值,需要的朋友可以參考下
    2021-09-09
  • elasticsearch中term與match的區(qū)別講解

    elasticsearch中term與match的區(qū)別講解

    今天小編就為大家分享一篇關(guān)于elasticsearch中term與match的區(qū)別講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02

最新評論