Shiro学习之RememberMe功能实现

前言

在网上看了一个开源的springboot项目,上面有非常全的springboot结合各种框架的配置,其中就有shiro,于是拿过来研究!
地址:https://github.com/wuyouzhuguli/SpringAll,从11开始看!他的项目里用的是Oracle数据库,如果你是MySQL数据库需要做对应的更换!
maven阿里云镜像下载不了Oracle的依赖,所以你需要自己准备对应jar包install本地!

更换MySQL数据库

一、更换依赖

		<!-- mysql驱动 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.47</version>
		</dependency>

二、更改配置

spring:
  datasource:
    druid:
      # 数据库访问配置, 使用druid数据源 
      type: com.alibaba.druid.pool.DruidDataSource
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true&autoReconnect=true&failOverReadOnly=false&zeroDateTimeBehavior=convertToNull
      username: root
      password: 123456

三、改换建表语句

他的Oracle建表语句并不能在MySQL里面直接用,因为类型都不匹配,不过这个并不是大问题,我这里贴上SQL

CREATE TABLE `t_user` (
  `id` int(20) NOT NULL,
  `username` varchar(255) DEFAULT NULL,
  `passwd` varchar(255) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `status` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

上几条数据:

INSERT INTO T_USER VALUES ('2', 'test', '7a38c13ec5e9310aed731de58bbc4214', TO_DATE('2017-11-19 17:20:21', 'YYYY-MM-DD HH24:MI:SS'), '0');
INSERT INTO T_USER VALUES ('1', 'mrbird', '42ee25d1e43e9f57119a00d0a39e5250', TO_DATE('2017-11-19 10:52:48', 'YYYY-MM-DD HH24:MI:SS'), '1');

这里密码是使用MD5盐值加密,代码请看util包下的加密工具,伪造数据这种事我就不详细说了!

Shiro的配置

当然这里我只贴核心代码,其余需要说明的地方请各位仔细看注释,有任何不懂得都可以留言或者进群交流!

import java.util.LinkedHashMap;

import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
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.Cookie;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.springboot.shiro.ShiroRealm;

@Configuration
public class ShiroConfig {
	
	@Bean
	public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		shiroFilterFactoryBean.setLoginUrl("/login");
		shiroFilterFactoryBean.setSuccessUrl("/index");
		shiroFilterFactoryBean.setUnauthorizedUrl("/403");
		
		LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
		
		filterChainDefinitionMap.put("/css/**", "anon");
		filterChainDefinitionMap.put("/js/**", "anon");
		filterChainDefinitionMap.put("/fonts/**", "anon");
		filterChainDefinitionMap.put("/img/**", "anon");
		filterChainDefinitionMap.put("/druid/**", "anon");
		filterChainDefinitionMap.put("/logout", "logout");
		filterChainDefinitionMap.put("/", "anon");
		filterChainDefinitionMap.put("/**", "user");
		
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		
		return shiroFilterFactoryBean;
	}
 
	@Bean  
    public SecurityManager securityManager(){  
       DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
       securityManager.setRealm(shiroRealm());
       //rememberMeManager添加到管理器里面
       securityManager.setRememberMeManager(rememberMeManager());
       return securityManager;  
    }  

    /**
    * @Description: 可见 LifecycleBeanPostProcessor 就是通过上述三个方法对Initializable和
	 * Destroyable这两个类的init方法和destroy方法进行内部调用来实现bean 的生命周期控制
    * @Param:
    * @return:
    * @Author: 朝花不迟暮
    * @Date: 2020/10/26
    */
	@Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }
	
	@Bean  
    public ShiroRealm shiroRealm(){  
       ShiroRealm shiroRealm = new ShiroRealm();  
       return shiroRealm;  
    }  
	
	/**
	 * cookie对象
	 * @return
	 */
	public SimpleCookie rememberMeCookie() {
		// 设置cookie名称,对应login.html页面的<input type="checkbox" name="rememberMe"/>
		SimpleCookie cookie = new SimpleCookie("rememberMe");
		// 设置cookie的过期时间,单位为秒,这里为一天
		cookie.setMaxAge(86400);
		return cookie;
	}
	
	/**
	 * cookie管理对象
	 * @return
	 */
	public CookieRememberMeManager rememberMeManager() {
		CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
		cookieRememberMeManager.setCookie(rememberMeCookie());
		// rememberMe cookie加密的密钥 
		cookieRememberMeManager.setCipherKey(Base64.decode("3AvVhmFLUs0KTA3Kprsdag=="));
		return cookieRememberMeManager;
	}
	
}

其实核心代码并不是很多,我这里也没有给全,像和数据库关联的dao层和业务相关的service层我是直接略过了,因为这并不是我们要说的话题。

控制层的改进

在他的源代码里虽然做了rememberMe功能,但是并没有在业务逻辑上体现出来,仅仅只是设置了一个cookies,我自己在他的基础上将这个功能实现出来,也不是很难!

	@GetMapping("/login")
	public String login(HttpServletRequest req) {
		Cookie[] cookies = req.getCookies();
		boolean rememberMe = false;
		for (Cookie cookie : cookies)
		{
			if(cookie.getName().equals("rememberMe")){
				System.out.println(cookie.getName().equals("rememberMe"));
				rememberMe = cookie.getName().equals("rememberMe");
				break;
			}
		}
		if(rememberMe){
			return "redirect:index";
		}
		System.out.println(rememberMe);
		return "login";
	}

其思路就是在跳转到登陆页的时候判断cookies里面是否有rememberMe,如果有说明这个用户之前已经登录过了那么就重定向到首页,反之则跳到登录页!

实际展示

浏览器输入:http://localhost:8080/web/login
在这里插入图片描述
输入 用户名:admin,密码:123456,点击记住我,这样浏览器上就有你的cookies
在这里插入图片描述
只要你不注销,你就可以直接进入首页,即使进入登录页也会重定向到首页!

咨询请找

QQ:707409741
群:118767976

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值