做网站公司的前景,越南做彩票网站是违法的吗,深圳建筑公司招聘信息,西红门模板网站建设目录
一、今日目标?
二、SpringBoot后端实现
2.1 新增UserLoginParam
2.2 修改UserController
2.3 UserServiceImpl代码
2.4 创建用户上下文工具类
2.5?通过token校验用户#xff08;重要#xff09;
2.6 创建WebMvcConfig
2.7 用户权限校验拦截器 一、今日目标 上…
目录
一、今日目标?
二、SpringBoot后端实现
2.1 新增UserLoginParam
2.2 修改UserController
2.3 UserServiceImpl代码
2.4 创建用户上下文工具类
2.5?通过token校验用户重要
2.6 创建WebMvcConfig
2.7 用户权限校验拦截器 一、今日目标 上篇文章链接【wiki知识库】08.添加用户登录功能–前端Vue部分修改-CSDN博客 这篇文章主要是实现一下用户登录功能的后端部分登录功能需要使用redis不懂redis可以看我之前的一篇文章。 Redis文章链接【Spring】SpringBoot整合Redis用Redis实现限流附Redis解压包_springboot 限流 redis-CSDN博客 那么为什么要用到Redis呢 这个问题关系到整个系统的用户校验当我们登录成功的时候后端会生成一个用于用户校验的token值然后把这个值传给前端每次用户请求后端的时候都要带上这个token值这个token的值当中记录了当前登录的用户是谁还有过期时间等信息这样子就可以防止那些没有登陆的用户去直接访问我们的后端调用接口。所以这个token还是需要妥善保管的一旦token丢失别人就可能用你的token去发送请求修改你的数据。 二、SpringBoot后端实现 2.1 新增UserLoginParam 这里也做了校验其实这个事情完全可以放到前端实现但是也要考虑到有直接调用接口的情况这时也要给出错误提示。 Data
public class UserLoginParam {NotEmpty(message 【用户名】不能为空)private String loginName;NotEmpty(message 【密码】不能为空)Pattern(regexp ^(?![0-9]$)(?![a-zA-Z]$)[0-9A-Za-z]{6,32}$, message 【密码】规则不正确)private String password;}2.2 修改UserController 直接上代码吧。这里拿到了用户的账号和用户的密码然后判断加密后的密码和数据库中取出来的用户密码是否相同如果相同那么就可以登陆。登陆后通过工具类生成一个不会重复的Long类型的值作为该用户的token然后以token为key登录用户创建的对象作为值保存到redis当中以便于后续用户访问接口时通过用户token来判断是哪个用户访问接口。 PostMapping(/login)public CommonResp login(Valid RequestBody UserLoginParam req) {req.setPassword(DigestUtils.md5DigestAsHex(req.getPassword().getBytes()));System.out.println(req);UserLoginVo userLoginResp userService.login(req);Long token snowFlake.nextId();userLoginResp.setToken(token.toString());redisTemplate.opsForValue().set(token.toString(), JSONObject.toJSONString(userLoginResp), 3600 * 24, TimeUnit.SECONDS);return new CommonResp(true,登录成功,userLoginResp);}GetMapping(/logout/{token})public CommonResp logout(PathVariable String token) {boolean res redisTemplate.delete(token);String message Boolean.TRUE.equals(res) ? 登出成功:登出失败;return new CommonResp(true,message,null);}2.3 UserServiceImpl代码 这个代码没有什么好说的就是查找一次数据库进行账号密码的匹配。 public UserLoginVo login(UserLoginParam req) {User userDb selectByLoginName(req.getLoginName());if (ObjectUtils.isEmpty(userDb)) {// 用户名不存在throw new RuntimeException(用户名不存在);} else {if (userDb.getPassword().equals(req.getPassword())) {// 登录成功UserLoginVo userLoginResp CopyUtil.copy(userDb, UserLoginVo.class);return userLoginResp;} else {// 密码不对throw new RuntimeException(密码错误);}}}2.4 创建用户上下文工具类 这个工具类用户用户登录后保存当前用户的上下文。 public class LoginUserContext implements Serializable {private static ThreadLocalUserLoginVo user new ThreadLocal();public static UserLoginVo getUser() {return user.get();}public static void setUser(UserLoginVo user) {LoginUserContext.user.set(user);}}2.5通过token校验用户重要 校验用户token需要使用到拦截器或者过滤器这里我使用拦截器进行用户token的校验。整体的校验流程如下 以下就是登录拦截器的代码 /*** 拦截器Spring框架特有的常用于登录校验权限校验请求日志打印*/
Component
public class LoginInterceptor implements HandlerInterceptor {private static final Logger LOG LoggerFactory.getLogger(LoginInterceptor.class);Resourceprivate RedisTemplate redisTemplate;Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// OPTIONS请求不做校验,// 前后端分离的架构, 前端会发一个OPTIONS请求先做预检, 对预检请求不做校验if (request.getMethod().toUpperCase().equals(OPTIONS)) {return true;}String path request.getRequestURL().toString();LOG.info(接口登录拦截path{}, path);//获取header的token参数String token request.getHeader(token);LOG.info(登录校验开始token{}, token);if (token null || token.isEmpty()) {LOG.info(token为空请求被拦截);response.setStatus(HttpStatus.UNAUTHORIZED.value());return false;}Object object redisTemplate.opsForValue().get(token);// 证明redis中的用户信息过期了需要重新登陆if (object null) {LOG.warn(token无效请求被拦截);response.setStatus(HttpStatus.UNAUTHORIZED.value());return false;} else {LOG.info(已登录{}, object);LoginUserContext.setUser(JSON.parseObject((String) object, UserLoginVo.class));return true;}}Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}接下来要把这个拦截器注册到配置当中。 2.6 创建WebMvcConfig 在config包下创建该类。这个类当中配置了两个拦截器一个是登录拦截器另一个是用户权限校验拦截器。用户校验拦截器下边再说。登录拦截器只需要部分接口进行拦截就可以了毕竟有的接口不需要登陆用户就可以访问。 有一点值得注意的是在这个配置类中配置的拦截器的顺序会影响校验结果校验的流程是根据你配置的拦截器的顺序从上往下校验的如果你把拦截器配置写反了就会出错。 addInterceptor 注册一个拦截器 addPathPatterns 该拦截器需要拦截的路径 excludePathPatterns 该拦截器不需要拦截的路径 Configuration
public class SpringMvcConfig implements WebMvcConfigurer {ResourceLoginInterceptor loginInterceptor;ResourceActionInterceptor actionInterceptor;public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor).addPathPatterns(/**).excludePathPatterns(/test/**,/redis/**,/user/login,/user/logout/**,/category/all,/ebook/list,/doc/all/**,/doc/find-content/**,);registry.addInterceptor(actionInterceptor).addPathPatterns(/*/save,/*/delete/**,/*/reset-password);}
}2.7 用户权限校验拦截器 看到下方的代码你应该知道了用户上下文的作用通过用户上下文拿到用户的信息来判断该用户是否有访问该接口的权利我们拒绝非admin用户外的用户进行增删改操作。 但是这种方法有点不太好不知道你们有没有感觉到一旦用户多了之后如果你想给用户分配权限你就要添加很多的用户在这里。所以一种更好的方式就是RBAC权限校验大家可以自己了解一下也有更好的权限校验框架SpringSecurity但是作为一个比较简单的项目引入这个框架的学习成本就太大了。 /*** 拦截器Spring框架特有的常用于登录校验权限校验请求日志打印*/
Component
public class ActionInterceptor implements HandlerInterceptor {private static final Logger LOG LoggerFactory.getLogger(ActionInterceptor.class);Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {// OPTIONS请求不做校验,// 前后端分离的架构, 前端会发一个OPTIONS请求先做预检, 对预检请求不做校验if (OPTIONS.equals(request.getMethod().toUpperCase())) {return true;}UserLoginVo userLoginResp LoginUserContext.getUser();if (admin.equals(userLoginResp.getLoginName())) {// admin用户不拦截return true;}LOG.info(操作被拦截);response.setStatus(HttpStatus.OK.value());CommonResp commonResp new CommonResp(false,普通用户暂不开放增删改操作,null);response.setContentType(application/json;charsetUTF-8);response.setCharacterEncoding(UTF-8);response.getWriter().print(JSONObject.toJSON(commonResp));return false;}}