这里要完成的功能有以下几点:
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";
}