SpringBoot整合Redis(三 ) 将登录成功产生的token存入redis

您所在的位置:网站首页 登录成功了吗 SpringBoot整合Redis(三 ) 将登录成功产生的token存入redis

SpringBoot整合Redis(三 ) 将登录成功产生的token存入redis

2023-06-20 14:48| 来源: 网络整理| 查看: 265

通过SpringBoot整合Redis(二 ) springboot整合缓存redis 对redis有了初步的理解。接下来探索一下如何运用Redis存取、识别当前登录用户信息。

本次实现:

1.用户登录,校验用户名密码后,登录成功产生token值,保存入Redis中,设置时效50分钟。

2.使用拦截器/ SpringAop技术,当用户调用其他接口时,必须传入token值,并且比较token值是否有效(存在),是否正确。

约定 :

一个用户只能拥有一个token,用户重复登录时,也就是说用户登录的token还有效时,用户再次登录,此时token有效期重置。

存入Redis格式为 : adminId : token,当用户调用除登录接口外的其他接口(我这测试只考虑了两个接口),进行校验,先校验adminId是否存在,再校验token是否正确。

1.登录成功返回信息

 2. 调用其他接口返回信息

一、配置信息,依赖信息的配置

依赖信息和Redis、数据库连接的配置信息,上一篇博客中有 SpringBoot整合Redis(二 ) springboot整合缓存redis

二、数据库的设置 DROP TABLE IF EXISTS `jc_user`; CREATE TABLE `jc_user` ( `id` tinyint(11) NOT NULL, `user_name` varchar(150) NOT NULL COMMENT '用户名', `password` varchar(150) DEFAULT NULL, `user_age` tinyint(11) DEFAULT NULL COMMENT '用户年龄', `user_sex` tinyint(11) NOT NULL COMMENT '用户性别(1表示男、2表示女、3表示未知)', `city` varchar(150) NOT NULL, `deleted_flag` tinyint(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 三、代码实现

工具类

1. JSON / 对象转换类

package user.login.utils; import java.util.List; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; /** * JSON工具类 * 将json和对象互相转换 * @author wulongwei * */ public class JsonUtils { // 定义jackson对象 private static final ObjectMapper MAPPER = new ObjectMapper(); /** * 将对象转换成json字符串。 * * @param data * @return */ public static String objectToJson(Object data) { try { String string = MAPPER.writeValueAsString(data); return string; } catch (JsonProcessingException e) { e.printStackTrace(); } return null; } /** * 将json结果集转化为对象 * * @param jsonData * @param beanType * @return */ public static T jsonToPojo(String jsonData, Class beanType) { try { T t = MAPPER.readValue(jsonData, beanType); return t; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 将json数据转换成pojo对象list * * @param jsonData * @param beanType * @return */ public static List jsonToList(String jsonData, Class beanType) { JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType); try { List list = MAPPER.readValue(jsonData, javaType); return list; } catch (Exception e) { e.printStackTrace(); } return null; } }

2.生成token类,登录成功后调用,如果同一用户重复登录,token的时效重置

package user.login.utils; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; /** * 生产token,如果同一用户重复登录,token的时效重置 * @author ASUS * */ @Service public class ProductToken { /** * 生成有时效的token * 之后调其他接口需要校验adminId和token值 * @param key * @param value */ public Map productToken(String key, String value) { Map infoMap = new HashMap(); if(redisTemplate.opsForValue().get(key) == null) { //将登陆的信息保存如redis redisTemplate.opsForValue().set(key, value); infoMap.put(key, value); } //设置token有效的时间 redisTemplate.expire(key, 3000, TimeUnit.SECONDS); return infoMap; } @Autowired private StringRedisTemplate redisTemplate; }

接口响应类  (调用接口后用统一的格式进行返回)

package user.login.base; import lombok.Data; import lombok.extern.slf4j.Slf4j; // 服务接口有响应 统一规范响应服务接口信息 @Data @Slf4j public class ResponseBase { private Integer rtnCode; private String msg; private Object data; public ResponseBase() { } public ResponseBase(Integer rtnCode, String msg, Object data) { super(); this.rtnCode = rtnCode; this.msg = msg; this.data = data; } public static void main(String[] args) { ResponseBase responseBase = new ResponseBase(); responseBase.setData("123456"); responseBase.setMsg("success"); responseBase.setRtnCode(200); System.out.println(responseBase.toString()); log.info("wulongwei..."); } @Override public String toString() { return "ResponseBase [rtnCode=" + rtnCode + ", msg=" + msg + ", data=" + data + "]"; } } package user.login.base; public class BaseApiService { public ResponseBase setResultError(Integer code, String msg) { return setResult(code, msg, null); } // 返回错误,可以传msg public ResponseBase setResultError(String msg) { return setResult(500, msg, null); } // 返回成功,可以传data值 public ResponseBase setResultSuccess(Object data) { return setResult(200, "处理成功", data); } // 返回成功,沒有data值 public ResponseBase setResultSuccess() { return setResult(200, "处理成功", null); } // 返回成功,沒有data值 public ResponseBase setResultSuccess(String msg) { return setResult(200, msg, null); } // 通用封装 public ResponseBase setResult(Integer code, String msg, Object data) { return new ResponseBase(code, msg, data); } }

实体类

package user.login.entity; import lombok.Data; import lombok.ToString; @Data @ToString public class User { private Integer userId; private String userName; private String password; private Integer userAge; private Short userSex; private String city; }

拦截器:在每次调用接口时进行拦截,校验用户传递的adminId和token是否有效并且正确

package user.login.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import user.login.interceptor.UserInterceptor; @Configuration //适配器 public class WebMvcConfigurer extends WebMvcConfigurationSupport { @Bean public UserInterceptor getUserInterceptor() { return new UserInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { /** * 拦截器按照顺序执行 */ registry.addInterceptor(getUserInterceptor()).excludePathPatterns("/user/login"); super.addInterceptors(registry); } } package user.login.interceptor; import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import user.login.base.ResponseBase; import user.login.entity.dto.TokenInfo; import user.login.utils.JsonUtils; public class UserInterceptor implements HandlerInterceptor { @Autowired private StringRedisTemplate redisTemplate; /** * 在请求处理之前进行调用(Controller方法调用之前) */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) { // 检查用户传递的 token是否合法 TokenInfo tokenInfo = this.getUserToKen(request); if (StringUtils.isBlank(tokenInfo.getAdminId()) && StringUtils.isBlank(tokenInfo.getToken())) { // 返回登录 System.out.println("没有传入对应的身份信息,返回登录"); return false; } try { String token = redisTemplate.opsForValue().get(tokenInfo.getAdminId()); if (token != null && token.equals(tokenInfo.getToken())) { System.out.println("校验成功"); return true; } else { System.out.println("校验失败,返回登录"); return false; } } catch (Exception e) { System.out.println("校验失败,对呀的信息匹配错误,返回登录"); return false; } } /** * 在cookie中获取用户传递的token */ private TokenInfo getUserToKen(HttpServletRequest request) { TokenInfo info = new TokenInfo(); String adminId = request.getHeader("adminId"); String token = request.getHeader("token"); if (StringUtils.isNotBlank(adminId) && StringUtils.isNotBlank(token)) { info.setAdminId(adminId); info.setToken(token); } return info; } /** * 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后) */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView mv) throws Exception { } /** * 在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行 (主要是用于进行资源清理工作) */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception ex) throws Exception { } public void returnErrorResponse(HttpServletResponse response, ResponseBase result) throws IOException, UnsupportedEncodingException { OutputStream out = null; try { response.setCharacterEncoding("utf-8"); response.setContentType("text/json"); out = response.getOutputStream(); out.write(JsonUtils.objectToJson(result).getBytes("utf-8")); out.flush(); } finally { if (out != null) { out.close(); } } } }

控制器层

package user.login.controller; import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import redis.demo.entity.UserDto; import user.login.base.ResponseBase; import user.login.service.UserService; @RestController @RequestMapping(value = "/user") public class UserController { /** * 登陆成功返回token给前台,之后每调一个接口都需要校验token之后有效 * @param username * @param passwrod * @return */ @PostMapping("/login") public ResponseBase UserLogin(@RequestBody @Valid UserDto userDto, HttpServletRequest request) { return userService.UserLogin(userDto.getUserName(), userDto.getPassword()); } /** * 查看用户的基本信息 * @param id * @return */ @GetMapping("/getUserInfo") public ResponseBase getUserInfo(Integer id) { return userService.getUserInfo(id); } @Autowired private UserService userService; }

service实现

package user.login.service.impl; import java.util.Map; import java.util.UUID; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import redis.demo.entity.User; import user.login.base.BaseApiService; import user.login.base.ResponseBase; import user.login.mapper.UserMapper; import user.login.service.UserService; import user.login.utils.ProductToken; @Service @Transactional public class UserServiceImpl extends BaseApiService implements UserService{ @Override public ResponseBase UserLogin(String username, String passwrod) { //1.校验登陆是否成功 User user = userMapper.getUserInfo(username, passwrod); //2.如果不成功返回提示 if (user == null) { return setResultError("账户名密码错误!!!"); } else { //3.如果成功,生产一个token String token = UUID.randomUUID().toString().replaceAll("-", ""); Map mapInfo = productToken.productToken(user.getId().toString(), token); //3.返回token信息(有效期50分钟) return setResultSuccess((Object)mapInfo); } } @Override public ResponseBase getUserInfo(Integer userId) { User user = userMapper.getUser(userId); if(user != null) { return setResultSuccess((Object)user); } else { return setResultSuccess("无此用户"); } } @Autowired private ProductToken productToken; @Autowired private UserMapper userMapper; }

mapper层

package user.login.mapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Result; import org.apache.ibatis.annotations.ResultMap; import org.apache.ibatis.annotations.Results; import org.apache.ibatis.annotations.SelectProvider; import org.springframework.stereotype.Repository; import redis.demo.entity.User; import user.login.mapper.sql.UserSqlProvider; @Repository @Mapper public interface UserMapper { /** * 通过用户名、密码获取用户信息 * @param userName * @param password * @return */ @SelectProvider(method = "select", type = UserSqlProvider.class) @Results(id="user", value={ @Result(column="id", property="userId", id=true), @Result(column="user_name", property="userName"), @Result(column="user_age", property="userAge"), @Result(column="user_sex", property="userSex"), @Result(column="city", property="city") }) User getUserInfo(String userName, String password); /** * 通过用户ID查询用户基本信息 * @param userId * @return */ @SelectProvider(method = "selectById", type = UserSqlProvider.class) @ResultMap(value="user") User getUser(Integer userId); } package user.login.mapper.sql; import org.apache.ibatis.jdbc.SQL; public class UserSqlProvider { public String select(final String userName, final String password) { String sql = new SQL() { { SELECT("*"); FROM("jc_user"); WHERE("deleted_flag = false AND user_name='" + userName + "' AND password= '" + password + "'"); } }.toString(); return sql; } public String selectById(final Integer userId) { String sql = new SQL() { { SELECT("*"); FROM("jc_user"); WHERE("deleted_flag = false AND id= '" + userId + "'"); } }.toString(); return sql; } }

启动类

@SpringBootApplication @MapperScan(basePackages= {"user.login.mapper"}) public class app { public static void main(String[] args) { SpringApplication.run(app.class, args); } }

代码链接

链接:https://pan.baidu.com/s/1YQC5MwfR4q3ckVgm1epalg  提取码:eagh   



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3