四、Springboot 整合Shiro---02认证---记住我

本章基于上一章节:三、Springboot 整合Shiro---01认证

在上一章节上进行了一些小小改动:

实现了用户登陆记住我功能:

一、将BeetlAction.class中的登陆方法提取到,新创建类中:

package com.xslde.action;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.CredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

/**
 * Created by xslde on 2018/7/21
 */
@Controller
public class LoginAction {


    @GetMapping("/login")
    public String login(){
        return "login.html";
    }

    @PostMapping("/login")
    public String login(String username,String password,boolean rememberMe,Model model){
        //判断用户名和密码为空
        if (StringUtils.isEmpty(username)||StringUtils.isEmpty(password)){
            model.addAttribute("msg","用户名和密码不能为空!");
            return "login.html";
        }

        //开始登录
        //实际开发中,用户名和密码错误,不给出明确提示
        try {
            SecurityUtils.getSubject().login(new UsernamePasswordToken(username,password,rememberMe));
        }catch (UnknownAccountException e){//未知用户异常
            model.addAttribute("msg","用户名错误!");
            return "login.html";
        }catch (LockedAccountException e){//账户锁定
            model.addAttribute("msg","账户被锁定!");
            return "login.html";
        }catch (CredentialsException e){//用户密码错误异常
            model.addAttribute("msg","用户密码错误!");
            return "login.html";
        }catch (Exception e){
            model.addAttribute("msg","其他异常!");
            return "login.html";
        }
        return "redirect:/index";
    }

}

二、对ShiroConf改动:

package com.xslde.configurer;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
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.mgt.WebSecurityManager;
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;

/**
 * @Author xslde
 * @Description
 * @Date 2018/7/20 16:25
 */
@Configuration
public class ShiroConf {


    //注入shiro过滤器
    @Bean("shiroFilterFactoryBean")
    public ShiroFilterFactoryBean shiroFilter(WebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 必须设置 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setLoginUrl("/login");  // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
        shiroFilterFactoryBean.setSuccessUrl("/index");// 登录成功后要跳转的链接
        Map<String, String> chains = new LinkedHashMap<>();
        chains.put("/logout","logout");//登出
        chains.put("/login", "anon");//anon表示可以匿名访问
        //chains.put("/**", "authc");//表示需要认证,才能访问
        chains.put("/**", "user");//表示需要认证或记a住我都能访问
        shiroFilterFactoryBean.setFilterChainDefinitionMap(chains);
        return shiroFilterFactoryBean;
    }


    //安全管理器
    @Bean
    public WebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置realm.
        securityManager.setRealm(shiroRealm());
        securityManager.setCacheManager(cacheManager());
        securityManager.setRememberMeManager(rememberMeManager());
        return securityManager;
    }

    //会话管理器
    @Bean
    public SessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        sessionManager.setGlobalSessionTimeout(1 * 60 * 60 * 1000);//session过期时间
        sessionManager.setDeleteInvalidSessions(true);//是否删除过期session
        sessionManager.setSessionIdCookie(rememberMeCookie());
        return sessionManager;
    }

    //Realm,里面是自己实现的认证和授权业务逻辑
    @Bean
    public ShiroRealm shiroRealm() {
        ShiroRealm shiroRealm = new ShiroRealm();
        shiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return shiroRealm;
    }

    //缓存管理
    @Bean
    public EhCacheManager cacheManager() {
        EhCacheManager cacheManager = new EhCacheManager();
        cacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
        return cacheManager;
    }

    //密码管理
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("md5"); //散列算法使用md5
        credentialsMatcher.setHashIterations(2);        //散列次数,2表示md5加密两次
        credentialsMatcher.setStoredCredentialsHexEncoded(true);//启用十六进制存储
        return credentialsMatcher;
    }

    //cookie管理
    @Bean
    public SimpleCookie rememberMeCookie() {
        SimpleCookie cookie = new SimpleCookie("rememberMe");
        cookie.setHttpOnly(true);
        cookie.setMaxAge(1 * 60 * 60);
        return cookie;
    }

    //记住我
    @Bean
    public CookieRememberMeManager rememberMeManager(){
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookie());
        //这个地方有点坑,不是所有的base64编码都可以用,长度过大过小都不行,没搞明白,官网给出的要么0x开头十六进制,要么base64
        cookieRememberMeManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));
    return cookieRememberMeManager;
    }
}

三、登陆页面改动:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
<form action="/login" method="post">
    <div>
        <span style="color: red;">${msg!}</span>
        <br>
        <div>
            <label>用户名称:</label>
            <input type="text" name="username" placeholder="请输入用户名称!">
        </div>
        <br>
        <div>
            <label>用户密码:</label>
            <input type="password" name="password" placeholder="请输入用户密码!">
        </div>
        <div>
            <input type="checkbox" checked="checked"  name="rememberMe" />记住我
        </div>
        <br>
        <input type="submit" value="登录" style="margin-left: 100px">
    </div>
</form>
</body>
</html>

项目启动后效果如下:

登陆成功后打开浏览器调试,可看见rememberMe:

到此,记住我功能实现完成。 

项目地址:springboot-example04

猜你喜欢

转载自blog.csdn.net/xslde_com/article/details/81137904