22. 尚融宝登录

需求

在这里插入图片描述

一、后端

集成JWT

  1. service-base模块,添加依赖
		<!--jwt-->
		<dependency>
			<groupId>io.jsonwebtoken</groupId>
			<artifactId>jjwt</artifactId>
		</dependency>
  1. 创建util

    JwtUtils.java

package com.indi.srb.base.util;

public class JwtUtils {

    private static long tokenExpiration = 24*60*60*1000;
    private static String tokenSignKey = "A1t2g3uigu123456";

    private static Key getKeyInstance(){
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        byte[] bytes = DatatypeConverter.parseBase64Binary(tokenSignKey);
        return new SecretKeySpec(bytes,signatureAlgorithm.getJcaName());
    }

    public static String createToken(Long userId, String userName) {
        String token = Jwts.builder()
                .setSubject("SRB-USER")
                .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
                .claim("userId", userId)
                .claim("userName", userName)
                .signWith(SignatureAlgorithm.HS512, getKeyInstance())
                .compressWith(CompressionCodecs.GZIP)
                .compact();
        return token;
    }

    /**
     * 判断token是否有效
     * @param token
     * @return
     */
    public static boolean checkToken(String token) {
        if(StringUtils.isEmpty(token)) {
            return false;
        }
        try {
            Jwts.parser().setSigningKey(getKeyInstance()).parseClaimsJws(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }


    public static Long getUserId(String token) {
        Claims claims = getClaims(token);
        Integer userId = (Integer)claims.get("userId");
        return userId.longValue();
    }

    public static String getUserName(String token) {
        Claims claims = getClaims(token);
        return (String)claims.get("userName");
    }

    public static void removeToken(String token) {
        //jwttoken无需删除,客户端扔掉即可。
    }

    /**
     * 校验token并返回Claims
     * @param token
     * @return
     */
    private static Claims getClaims(String token) {
        if(StringUtils.isEmpty(token)) {
            // LOGIN_AUTH_ERROR(-211, "未登录"),
            throw new BusinessException(ResponseEnum.LOGIN_AUTH_ERROR);
        }
        try {
            Jws<Claims> claimsJws = Jwts.parser().setSigningKey(getKeyInstance()).parseClaimsJws(token);
            Claims claims = claimsJws.getBody();
            return claims;
        } catch (Exception e) {
            throw new BusinessException(ResponseEnum.LOGIN_AUTH_ERROR);
        }
    }
}

集成swapper-bootstrap

service-base模块

		<!--swagger-bootstrap-->
		<dependency>
			<groupId>com.github.xiaoymin</groupId>
			<artifactId>swagger-bootstrap-ui</artifactId>
			<version>1.9.2</version>
		</dependency>

vo

LoginVO.java

package com.indi.srb.core.pojo.vo;

@Data
@ApiModel(description = "登录对象")
public class LoginVO {
    @ApiModelProperty(value = "用户类型")
    private Integer userType;
    
    @ApiModelProperty(value = "手机号")
    private String mobile;
    
    @ApiModelProperty(value = "密码")
    private String password;
}

UserInfoVO.java

package com.indi.srb.core.pojo.vo;

@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description="用户信息对象")
public class UserInfoVO {
    @ApiModelProperty(value = "1:出借人 2:借款人")
    private Integer userType;

    @ApiModelProperty(value = "手机号")
    private String mobile;

    @ApiModelProperty(value = "用户密码")
    private String password;

    @ApiModelProperty(value = "用户昵称")
    private String nickName;

    @ApiModelProperty(value = "用户姓名")
    private String name;

    @ApiModelProperty(value = "用户访问令牌")
    private String token;
}

entity

UserLoginRecord.java

    public UserLoginRecord(Long userId, String ip) {
        this.userId = userId;
        this.ip = ip;
    }

service

UserInfoService.java

    UserInfoVO login(LoginVO loginVO, String ip);

UserInfoServiceImpl.java

	@Resource
    private UserLoginRecordMapper userLoginRecordMapper;

	@Override
    public UserInfoVO login(LoginVO loginVO, String ip) {
        String mobile = loginVO.getMobile();
        String password = loginVO.getPassword();
        Integer userType = loginVO.getUserType();

        // 用户是否存在
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("mobile", mobile);
        queryWrapper.eq("user_type", userType);
        UserInfo userInfo = baseMapper.selectOne(queryWrapper);

        Assert.notNull(userInfo, ResponseEnum.LOGIN_MOBILE_ERROR);
        
        // 密码是否正确
        Assert.equals(MD5.encrypt(password), userInfo.getPassword(), ResponseEnum.LOGIN_PASSWORD_ERROR);

        // 用户是否被锁定
        Assert.equals(userInfo.getStatus(), UserInfo.STATUS_NORMAL, ResponseEnum.LOGIN_LOCKED_ERROR);

        // 记录登录日志
        UserLoginRecord userLoginRecord = new UserLoginRecord(userInfo.getId(),ip);
        userLoginRecordMapper.insert(userLoginRecord);

        String token = JwtUtils.createToken(userInfo.getId(), userInfo.getName());
        
        UserInfoVO userInfoVO = new UserInfoVO(
                userType,
                mobile,
                password,
                userInfo.getNickName(),
                userInfo.getName(),
                token
        );
        return userInfoVO;
    }

controller

UserInfoController.java

    @ApiOperation("用户登录")
    @PostMapping("/login")
    public R login(@RequestBody LoginVO loginVO, HttpServletRequest request) {
        String mobile = loginVO.getMobile();
        String password = loginVO.getPassword();

        Assert.notEmpty(mobile, ResponseEnum.MOBILE_NULL_ERROR);
        Assert.notEmpty(password, ResponseEnum.PASSWORD_NULL_ERROR);

        UserInfoVO userInfoVO = userInfoService.login(loginVO, request.getRemoteAddr());
        return R.ok().setData("userInfo", userInfoVO);
    }

    @ApiOperation("校验令牌")
    @GetMapping("/checkToken")
    public R checkToken(HttpServletRequest request) {
        // 从请求头中获取token
        String token = request.getHeader("token");
        // 检查token是否有效
        boolean result = JwtUtils.checkToken(token);
        if (result) {
            return R.ok();
        } else {
            return R.setResult(ResponseEnum.LOGIN_AUTH_ERROR);
        }
    }

二、swagger测试

访问

http://localhost:8110/doc.html

添加全局参数

在这里插入图片描述

刷新页面,测试

在这里插入图片描述

三、前端

登录界面

pages/login.vue

methods: {
    //登录
    login() {
      if (!this.userInfo.mobile) {
        this.$message.error('手机号不能为空')
        return
      }

      if (!this.userInfo.password) {
        this.$message.error('密码不能为空')
        return
      }

      this.$axios
        .$post('/api/core/userInfo/login', this.userInfo)
        .then((response) => {
          cookie.set('userInfo',response.data.userInfo)
          window.location.href='/user'
        })
    },
  },
}

页面头信息

components/AppHeader.vue

  methods: {
    //显示用户信息
    showInfo() {
      let userInfo = cookie.get('userInfo')
      if (!userInfo) {
        console.log('cookie不存在')        
        this.userInfo = null
        return
      }

      userInfo = JSON.parse(userInfo)

      // 需要在请求头中设置token
      // this.$axios({
      //   url: '/api/core/userInfo/checkToken',
      //   method: 'get',
      //   headers: {
      //     token: userInfo.token,
      //   },
      // }).then((response) => {
      //   this.userInfo = userInfo
      // })

      // 后面添加了拦截器,可以不用在请求头中设置
      this.$axios.$get('/api/core/userInfo/checkToken').then((response) => {
        this.userInfo = userInfo
      })
    },

    //退出
    logout() {
      cookie.set('userInfo', '')
      window.location.href = '/login'
    },
  },

axios拦截器

plugins/axios.js

统一添加header,这样就不需要每次向后端请求的时候添加token了

import { Message } from 'element-ui'
import cookie from 'js-cookie'

export default function({ $axios, redirect }) {
  // 请求拦截
  $axios.onRequest((config) => {
    // 添加请求头:token
    // 这样就不需要每次向后端请求的时候添加token了
    let userInfo = cookie.get('userInfo')
    if (userInfo) {
      // debugger
      userInfo = JSON.parse(userInfo)
      config.headers['token'] = userInfo.token
    }
    console.log('Making request to ' + config.url)
  })

  // 请求失败
  $axios.onRequestError((error) => {
    console.log('onRequestError', error) // for debug
  })

  // 响应拦截:处理未登录状况
  $axios.onResponse((response) => {
    console.log('Reciving resposne', response)
    if (response.data.code === 0) {
      return response
    } else if (response.data.code === -211) {
      console.log('用户校验失败')
      // debugger
      cookie.set('userInfo', '')
      window.location.href = '/'
    } else {
      Message({
        message: response.data.message,
        type: 'error',
        duration: 5 * 1000,
      })
      return Promise.reject(response)
    }
  })

  // 通信失败
  $axios.onResponseError((error) => {
    console.log('onResponseError', error) // for debug
  })
}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
QueryWrapper是MyBatis-Plus框架中的一个查询条件封装类,用于构建复杂的查询条件。它可以方便地通过链式调用的方式添加多个条件。根据给出的引用内容,QueryWrapper可以通过in、le、orderByDesc、orderByAsc等方法来实现多条件查询。 比如,可以使用queryWrapper.in("id", 1, 2, 3)方法来查询id为1、2、3的记录;使用queryWrapper.le("id", 3)方法来查询id小于等于3的记录。 此外,QueryWrapper还可以实现多条件的排序。比如,可以使用queryWrapper.orderByDesc("age").orderByAsc("id")方法来按照年龄降序排序,如果年龄相同则按照id升序排序。 综上所述,QueryWrapper可以通过多个方法的组合来实现多条件查询,包括in、le、orderByDesc、orderByAsc等方法。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [尚融宝04-mybatis-plus插件和条件构造器](https://blog.csdn.net/m0_62946761/article/details/129614633)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Mybatis-plus条件构造器各种用法(三)](https://blog.csdn.net/slxysyka/article/details/122569373)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值