spring+redis+Interceptor拦截器实现登录功能

版权声明:本文为博主原创文章,欢迎转载,转载请注明作者、原文超链接 https://blog.csdn.net/weixin_43863007/article/details/88699458

这里要完成的功能有以下几点:

1. 登录时用户名密码的验证
2. 登录成功后用户数据存到session中
3. 使用cookie实现3天免登陆效果
4. 使用rides存取用户信息
5. 使用拦截器过滤非法请求
6. 退出登录清空session,cookie,rides

1.登录的用户名密码从js接收传到controller调用service方法做处理,这里直接写service中的处理过程:

1. 登录时根据邮箱和密码进行登录,根据查询结果判断邮箱验证有没有激活决定能否登录
2. 登录验证没有问题后将用户信息存储到session中方便使用
3. 登录成功将用户信息转换成gson格式存储在rides中,需要gson依赖
4. 用一个随机字符串作为key,转化成gson的user对象作为value,存入rides中,方面后边取用
5. 创建一个cookie以键值对的方式只存rides中对象数据的key方便从rides中取值,也保证了cookie的安全
6. 给cookie设置失效时间和作用域范围然后写入cookie
7. 这样就实现了登录功能

@Service
public class UserServiceImp extends BaseServiceImpl<User> implements UserService {
	@Autowired
	UserMapper usermapper;
	//注入一个redis的连接池对象
	@Autowired
	JedisPool jedisPool;
	//登录功能根据邮箱密码和激活状态
	@Override
	public int selectByEmailaPwdaState(User user,HttpSession httpsession,HttpServletResponse response) {
		String password = MyUtil.md5(user.getPassword());
		String email = user.getEmail();
		User user1 = usermapper.selectByEmailaPwdaState(email, password);
		if(user1!=null){
			if(user1.getActivationState()==1){
				httpsession.setAttribute("user", user1);
				//登录成功后将对象存到redis中,转换成gson字符串格式,cookie从redis中获取对象
				//通过连接池对象获得一个连接,相当于从连接池中拿一个连接
				Jedis jedis = jedisPool.getResource();
				Gson gson = new Gson();//创建gson对象
				//key用随机字符串将转化成json格式的对象存入redis
				String key = UUID.randomUUID().toString();
				jedis.setex("SESSION:"+key, 60*60*24*3, gson.toJson(user1));
				//登录成功后存入cookie,实现免登陆效果
				//token授权的意思,key随机字符用来调用redis中对象字符串
				Cookie cookie = new Cookie("token",key);//创建cookie,里面存redis的key
				cookie.setMaxAge(60*60*24*3);//设置cookie的失效时间
				cookie.setPath("/");//设置cookie作用域在当前项目下
				response.addCookie(cookie);//写入cookie
				
				return 1;//用户存在状态为1
			}else if(user1.getActivationState()==0){
				return 2;//用户存在状态为0
			}
		}
		return 0;//用户不存在
	}
}
3.配置rides和gson的依赖包,以及在applicationContext.xml中配置rides的连接池,和rides的properties文件的相关值
		<!-- jedis工具包 -->
		<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
			<version>2.4.2</version>
		</dependency>
		<!-- gson依赖,用于把对象存在redis中转换格式-->
		<dependency>
			<groupId>com.google.code.gson</groupId>
			<artifactId>gson</artifactId>
			<version>2.8.5</version>
		</dependency>
<!-- Redis连接池的配置 -->
	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<property name="maxTotal" value="${redis.pool.maxActive}" />
		<property name="maxIdle" value="${redis.pool.maxIdle}" />
		<property name="minIdle" value="${redis.pool.minIdle}" />
		<property name="maxWaitMillis" value="${redis.pool.maxWait}" />
		<property name="testOnBorrow" value="${redis.pool.testOnBorrow}" />
		<property name="testOnReturn" value="${redis.pool.testOnReturn}" />
	</bean>
	<!-- 在java中需要调用redis的地方注入jedisPool这个连接池对象 -->
	<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
		<constructor-arg index="0" ref="jedisPoolConfig" />
		<constructor-arg index="1" value="${redis.hostName}" />
		<constructor-arg index="2" value="${redis.port}" />
		<constructor-arg index="3" value="${redis.timeout}" />
		<!--Redis密码 -->
		<!--<constructor-arg index="4" value="${redis.password}" /> -->
	</bean>
properties文件中的相关值
redis.hostName=192.168.1.238
redis.port=6379
redis.password=
redis.timeout=5000
redis.pool.maxActive=300
redis.pool.maxIdle=250
redis.pool.minIdle=200
redis.pool.maxWait=3000
redis.pool.testOnBorrow=true
redis.pool.testOnReturn=true
4.拦截器过滤非法请求,在拦截器中需要从rides中取值用来cookie免登陆效果

spring.xml中拦截器的配置文件,以及拦截器的映射文件的bean创建

<!-- spring拦截器 -->
	<mvc:interceptors>
		<mvc:interceptor>
			<!-- 需要拦截的请求 /**代表拦截所有请求 -->
			<mvc:mapping path="/**"/> 
			<!-- 排除不需要拦截的请求 -->
			<mvc:exclude-mapping path="/static/js/**"/>
			<mvc:exclude-mapping path="/static/css/**"/>
			<mvc:exclude-mapping path="/login.jsp"/>
			<mvc:exclude-mapping path="/user/login"/>
			<bean class="com.hxzy.interceptors.Interceptors"></bean>
		</mvc:interceptor>
	</mvc:interceptors>

拦截器中在请求之前拦截判断

1. 这里用到了rides,需要先创建一个连接池对象获取一个连接
2. 得到所有的cookie遍历看有没有key键名字叫token的,指向的是redis中登录时存的user对象的key
3. 有的话取出token对应的key键看是否能从rides中查出响应的数据结果
4. 如果能说明这个用户是存在的可以放行
5. 但是由于退出的时候session清空了,这里放行前需要再把rides中的gson数据格式转换成user对象存到session中
6. 其他情况统统拦截直接跳转到登录页面

 拦截器
public class Interceptors implements HandlerInterceptor{
	//注入一个redis的连接池对象
	@Autowired
	JedisPool jedisPool;
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception {System.out.println("方法结束之后");}
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception {System.out.println("方法调用之后");}
	public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object arg2) throws Exception {
		System.out.println("请求之前拦截");
		//通过连接池对象获得一个连接,相当于从连接池中拿一个连接
		Jedis jedis = jedisPool.getResource();
		
		//根据cookie来判断是否登录
		//得到所有的cookie
		Cookie[] cookies = req.getCookies();
		for(Cookie cookie : cookies){
			//查看cookie中有没有叫token的授权码key,指向的是redis中登录时存的user对象
			if(cookie.getName().equals("token")){
				//如果有取出token中的key授权码value去核对
				String token = cookie.getValue();
				//在redis中看该授权码对应的信息是否正确
				String result = jedis.get("SESSION:"+token);
				if(result==null){
					//如果在redis中没有对应的信息跳转到登录页面
					resp.sendRedirect("/login.jsp");
					return false;
				}else{
					//不等于空说明已登录,通过
					//因为是免登陆效果当退出的时候session已经被清空,需要在这里重新把对象存到session
					Gson gson = new Gson();
					User user = gson.fromJson(result, User.class);
					req.getSession().setAttribute("user", user);
					return true;
				}
			}
		}
		//如果cookie中没有存token也跳转到登录页面
		resp.sendRedirect("/login.jsp");
		return false;
	}
}
5.退出登录功能:

1. 清空session
2. 遍历cookie找到cookie中token对应的key从rides中删除
3. 把cookie覆盖

@Override
	public void logout(HttpServletRequest request,HttpServletResponse response) {
		//清空session
		request.getSession().invalidate();
		//清空cookie
		Cookie[] cookies = request.getCookies();
		for(Cookie cookie : cookies){
			if(cookie.getName().equals("token")){
				String value = cookie.getValue();
				//清除redis,删除掉某个key
				Jedis jedis = jedisPool.getResource();
				jedis.del("SESSION:"+value);
				//将cookie失效时间设置成0,从新写入cookie将之前的覆盖掉
				cookie.setMaxAge(0);
				response.addCookie(cookie);
				return;
			}
		}
	}
//退出登录
	@RequestMapping("logout")
	public String getall(HttpServletRequest request,HttpServletResponse response){
		us.logout(request, response);
		return "redirect:/login.jsp";
	}

猜你喜欢

转载自blog.csdn.net/weixin_43863007/article/details/88699458