首页 > 其他分享 >登录功能

登录功能

时间:2022-10-18 08:45:25浏览次数:72  
标签:功能 return String 登录 accessToken response token public

登录开发

核心逻辑

  • 通过mail找数据库记录
  • 获取盐,和当前传递的密码就行加密后匹配
  • 生成token令牌

JWT

  • JWT

    • JWT 是一个开放标准,它定义了一种用于简洁,自包含的用于通信双方之间以 JSON 对象的形式安全传递信息的方法。 可以使用 HMAC 算法或者是 RSA 的公钥密钥对进行签名
    • 简单来说: 就是通过一定规范来生成token,然后可以通过解密算法逆向解密token,这样就可以获取用户信息
          	  {
                    id:888,
                    name:'小D',
                    expire:10000
                }
                
                funtion 加密(object, appsecret){
                    xxxx
                    return base64( token);
                }
    
                function 解密(token ,appsecret){
    
                    xxxx
                    //成功返回true,失败返回false
                }
    
    • 优点

      • 生产的token可以包含基本信息,比如id、用户昵称、头像等信息,避免再次查库
      • 存储在客户端,不占用服务端的内存资源
    • 缺点

      • token是经过base64编码,所以可以解码,因此token加密前的对象不应该包含敏感信息,如用户权限,密码等

      • 如果没有服务端存储,则不能做登录失效处理,除非服务端改秘钥

  • JWT格式组成 头部、负载、签名

    • header+payload+signature
      • 头部:主要是描述签名算法
      • 负载:主要描述是加密对象的信息,如用户的id等,也可以加些规范里面的东西,如iss签发者,exp 过期时间,sub 面向的用户
      • 签名:主要是把前面两部分进行加密,防止别人拿到token进行base解密后篡改token
  • 关于jwt客户端存储

    • 可以存储在cookie,localstorage和sessionStorage里面
  • controller

@ApiOperation("用户登录")
@PostMapping("login")
public JsonData login(@ApiParam("用户登录对象") @RequestBody UserLoginRequest userLoginRequest) {
    JsonData jsonData = userService.login(userLoginRequest);
    return jsonData;
}
  • service
    /**
     * 用户登录
     * @param userLoginRequest
     * @return
     */
    @Override
    public JsonData login(UserLoginRequest userLoginRequest) {
        List<UserDO> userDOList = userMapper.selectList(new QueryWrapper<UserDO>().eq("mail", userLoginRequest.getMail()));
        if (userDOList != null && userDOList.size() == 1) {
            //已注册
            UserDO userDO = userDOList.get(0);
            String cryptPwd = Md5Crypt.md5Crypt(userLoginRequest.getPwd().getBytes(), userDO.getSecret());
            if (cryptPwd.equals(userDO.getPwd())) {
                //生成token
                LoginUser loginUser = LoginUser.builder().build();
                BeanUtils.copyProperties(userDO,loginUser);
                String accessToken = JWTUtil.geneJsonWebToken(loginUser);
                return JsonData.buildSuccess(accessToken);
            } else {
                return JsonData.buildResult(BizCodeEnum.ACCOUNT_PWD_ERROR);
            }
        } else {
            //未注册
            return JsonData.buildResult(BizCodeEnum.ACCOUNT_UNREGISTER);
        }
    }

登录拦截器开发

  • 解密JWT
  • 传递登录用户信息
    • attribute传递
    • threadLocal传递
  • SpringBoot拦截器代码开发
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
try {
            String accessToken = request.getHeader("token");
            if (accessToken == null) {
                accessToken = request.getParameter("token");
            }

            if (StringUtils.isNotBlank(accessToken)) {
                Claims claims = JWTUtil.checkJWT(accessToken);
                if (claims == null) {
                    //告诉登录过期,重新登录
                    CommonUtil.sendJsonMessage(response, JsonData.buildError("登录过期,重新登录"));
                    return false;
                }

                Long id = Long.valueOf( claims.get("id").toString());
                String headImg = (String) claims.get("head_img");
                String mail = (String) claims.get("mail");
                String name = (String) claims.get("name");

			   //TODO 用户信息传递
                return true;
            }
        } catch (Exception e) {
            log.error("拦截器错误:{}",e);
        }
        CommonUtil.sendJsonMessage(response, JsonData.buildError("token不存在,重新登录"));
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

ThreadLocal传递信息

  • ThreadLocal
全称thread local variable(线程局部变量)功用非常简单,使用场合主要解决多线程中数据因并发产生不一致问题。

ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享,这样的结果是耗费了内存,但大大减少了线程同步所带来性能消耗,也减少了线程并发控制的复杂度。 

总结起来就是:同个线程共享数据

注意:ThreadLocal不能使用原子类型,只能使用Object类型
  • 核心应用场景
ThreadLocal 用作每个线程内需要独立保存信息,方便同个线程的其他方法获取该信息的场景。

每个线程获取到的信息可能都是不一样的,前面执行的方法保存了信息后,后续方法可以通过ThreadLocal 直接获取到,避免了传参,类似于全局变量的概念,比如用户登录令牌解密后的信息传递(还有用户权限信息、从用户系统获取到的用户名、用户ID)

image-20221018082425088

  • 配置token解密信息传递
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {

    public static ThreadLocal<LoginUser> threadLocal = new ThreadLocal<>();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String accessToken = request.getHeader("token");

        if (accessToken == null) {
            accessToken = request.getParameter("token");
        }

        if (StringUtils.isNotBlank(accessToken)) {
            Claims claims = JWTUtil.checkJWT(accessToken);
            if (claims == null) {
                CommonUtil.sendJsonMessage(response, JsonData.buildResult(BizCodeEnum.ACCOUNT_UNLOGIN));
                return false;
            }

            long userId = Long.valueOf(claims.get("id").toString());
            String headImg = (String) claims.get("head_img");
            String name = (String) claims.get("name");
            String mail = (String) claims.get("mail");

            LoginUser loginUser = LoginUser
                    .builder()
                    .headImg(headImg)
                    .name(name)
                    .id(userId)
                    .mail(mail).build();

            //通过ThreadLocal传递信息
            threadLocal.set(loginUser);

            return true;
        }

        CommonUtil.sendJsonMessage(response, JsonData.buildResult(BizCodeEnum.ACCOUNT_UNLOGIN));
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

登录拦截器路径配置和开发

  • 拦截器配置
    • 拦截路径
    • 不拦截路径
@Configuration
@Slf4j
public class InterceptorConfig  implements WebMvcConfigurer {


    public  LoginInterceptor loginInterceptor(){
        return new LoginInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        registry.addInterceptor(loginInterceptor())
                //拦截的路径
                .addPathPatterns("/api/user/*/**","/api/address/*/**")

                //排查不拦截的路径
                .excludePathPatterns("/api/user/*/send_code","/api/user/*/captcha",
                        "/api/user/*/register","/api/user/*/login","/api/user/*/upload");

    }
}

标签:功能,return,String,登录,accessToken,response,token,public
From: https://www.cnblogs.com/youngleesin/p/16801330.html

相关文章

  • delphi TcxGrid制作一个动态授权修改数据的功能
    需求明细:1.表格TV申购清单,默认OptionsData--Editing:true可写权限2.默认列属性[申购数量,单重,用途,需求日期]Options---Editing:true常规情况下,这几列......
  • mac上的类xshell的工具termius功能研究测试,附mac上安装brew并解压asar文件
    1.安装brew1.1nodejsbrew的安装目录在/usr/local/Cellar,我们以安装nodejs为例子,只需要执行:brewinstallnodejs1.2brew使用中科大源安装brew /usr/bin/ruby-e"$(......
  • Vue实现用户登录管理
    Vue实现用户登录管理vuex+cookie+router业务流程:1、用户在注册时提交信息,后端生成用户的数据2、用户登录时通过网页表单提交用户名和密码,后台根据提交的数据生成to......
  • 【Azure 应用服务】登录App Service 高级工具 Kudu站点的 Basic Auth 方式
    问题描述从AzureAppService的页面中,直接跳转到高级管理工具Kudu站点(https://<yourappservicename>.scm.chinacloudsites.cn/)时,可以自动使用AAD用户(即登录Azure门......
  • Linux 下配置 hosts 并设置免密登录
    Linux下配置hosts并设置免密登录作者:Grey原文地址:博客园:Linux下配置hosts并设置免密登录CSDN:Linux下配置hosts并设置免密登录说明实现Linux下(基于CentOS......
  • python爬虫从0到1 -urllib_Cookie登录
    前言当我们进行某项数据采集的时候,有时会让我们进行登录,那我们要怎样去解决这个问题呢?为了不让我们爬取这些数据,又采取了怎么样的反爬措施呢?下面就让我们带着这些问题去一探......
  • win11免密登录linux
    在win端和linux上分别创建本机的公钥和私钥,输入命令后连续三次回车ssh-keygen-trsa进入ssh查看密钥生成情况PSC:\Users\xiaoyang>cd.\.ssh\PSC:\Users\xiaoyang......
  • 抓包分析-充分使用BOSS直聘的VIP功能
    前提:BOSS直聘VIP用户通过网页抓包分析可得:VIP功能的聊天消息设置优先提醒boss的API接口为:https://www.zhipin.com/wapi/zpitem/web/online/setRemind请求方式:post传输......
  • 网络层功能概述
    ++主要任务是把分组从源端传到目的地,为分组交换网上的不同主机提供通信服务。网络层的传输单位是数据报(数据报是一个比较长的数据,但是分组是把这个数据报进行切割而划分出的......
  • Python爬虫之基于selenium实现12306模拟登录
    参考:https://blog.csdn.net/m0_54490473/article/details/122751814解决了个主要问题,滑块验证错误。文件由:vscode编写,浏览器驱动为EDGE.驱动下载地址:https://develop......