最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

前言

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

springboot 整合 shiro 之實現(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);
        // 實現(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必須認證
        filterChainDefinitionMap.put("/user/update", "authc");
        // index.html必須認證
        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;
    }

	// 實現(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;
    }

	// 實現(xiàn)記住我,所需要的配置
    @Bean
    public CookieRememberMeManager cookieRememberMeManager() {
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(simpleCookie());
        // rememberMe cookie加密的密鑰 建議每個項目都不一樣 默認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里認證方法設(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 = "用戶認證失敗";
            }
        }
        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 為例進行登錄,如下

在這里插入圖片描述

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

在這里插入圖片描述

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

在這里插入圖片描述

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

在這里插入圖片描述

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

在這里插入圖片描述

源碼:springboot-shiro

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

相關(guān)文章

  • 淺談Mybatis+mysql 存儲Date類型的坑

    淺談Mybatis+mysql 存儲Date類型的坑

    這篇文章主要介紹了淺談Mybatis+mysql 存儲Date類型的坑,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • Java 生成任意長度的驗證碼過程解析

    Java 生成任意長度的驗證碼過程解析

    這篇文章主要介紹了Java 生成任意長度的驗證碼過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-10-10
  • java將m3u8格式轉(zhuǎn)成視頻文件的方法

    java將m3u8格式轉(zhuǎn)成視頻文件的方法

    這篇文章主要介紹了如何java將m3u8格式轉(zhuǎn)成視頻文件,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-03
  • 淺談Java四種線程池及new Thread的弊端

    淺談Java四種線程池及new Thread的弊端

    本文主要介紹了淺談Java四種線程池及new Thread的弊端,詳細的介紹了newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor四種的使用,感興趣的可以了解一下
    2024-01-01
  • 利用Java的Struts框架實現(xiàn)電子郵件發(fā)送功能

    利用Java的Struts框架實現(xiàn)電子郵件發(fā)送功能

    這篇文章主要介紹了利用Java的Struts框架實現(xiàn)電子郵件發(fā)送功能,Struts框架是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下
    2015-12-12
  • JAVA中@ApiModel和@ApiModelProperty注解實戰(zhàn)代碼

    JAVA中@ApiModel和@ApiModelProperty注解實戰(zhàn)代碼

    這篇文章主要給大家介紹了關(guān)于JAVA中@ApiModel和@ApiModelProperty注解的相關(guān)資料,@ApiModel注解是用在接口相關(guān)的實體類上的注解,它主要是用來對使用該注解的接口相關(guān)的實體類添加額外的描述信息,常常和@ApiModelProperty注解配合使用,需要的朋友可以參考下
    2024-03-03
  • Mybatis動態(tài)調(diào)用表名和字段名的解決方法

    Mybatis動態(tài)調(diào)用表名和字段名的解決方法

    今天在項目開發(fā)中有個業(yè)務(wù)是需要限制各個用戶對某些表里的字段查詢以及某些字段是否顯示,這種情況下,就需要構(gòu)建sql來動態(tài)傳入表名、字段名了,下面給大家介紹mybatis動態(tài)調(diào)用表名和字段名的解決方法,一起看看吧
    2016-10-10
  • Java文件斷點續(xù)傳實現(xiàn)原理解析

    Java文件斷點續(xù)傳實現(xiàn)原理解析

    這篇文章主要介紹了Java文件斷點續(xù)傳實現(xiàn)原理解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-05-05
  • Spring Boot實現(xiàn)圖片上傳/加水印一把梭操作實例代碼

    Spring Boot實現(xiàn)圖片上傳/加水印一把梭操作實例代碼

    這篇文章主要給大家介紹了關(guān)于Spring Boot實現(xiàn)圖片上傳/加水印一把梭操作的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11
  • Flink作業(yè)Task運行源碼解析

    Flink作業(yè)Task運行源碼解析

    這篇文章主要為大家介紹了Flink作業(yè)Task運行源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12

最新評論

浦东新区| 龙门县| 安龙县| 清涧县| 赤城县| 眉山市| 偏关县| 醴陵市| 博客| 郸城县| 额敏县| 文昌市| 富川| 达州市| 丹凤县| 太康县| 溆浦县| 新化县| 广昌县| 永安市| 昌邑市| 吉安县| 芜湖市| 永川市| 普格县| 五指山市| 旺苍县| 礼泉县| 商水县| 德州市| 清涧县| 临澧县| 广饶县| 成安县| 都兰县| 双峰县| 黎城县| 三江| 霍林郭勒市| 太康县| 彰武县|