Browse Source

!16 登录改为token方式

Merge pull request !16 from blue/v_1.1.0
master
blue 3 years ago
committed by Gitee
parent
commit
2dfa7985ba
No known key found for this signature in database GPG Key ID: 173E9B9CA92EEF8F
  1. 6
      im-platform/pom.xml
  2. 3
      im-platform/src/main/java/com/bx/implatform/ImplatformApp.java
  3. 36
      im-platform/src/main/java/com/bx/implatform/config/MvcConfig.java
  4. 172
      im-platform/src/main/java/com/bx/implatform/config/WebSecurityConfg.java
  5. 8
      im-platform/src/main/java/com/bx/implatform/contant/Constant.java
  6. 48
      im-platform/src/main/java/com/bx/implatform/controller/LoginController.java
  7. 32
      im-platform/src/main/java/com/bx/implatform/controller/RegisterController.java
  8. 22
      im-platform/src/main/java/com/bx/implatform/dto/LoginDTO.java
  9. 4
      im-platform/src/main/java/com/bx/implatform/dto/RegisterDTO.java
  10. 11
      im-platform/src/main/java/com/bx/implatform/enums/ResultCode.java
  11. 48
      im-platform/src/main/java/com/bx/implatform/interceptor/AuthInterceptor.java
  12. 10
      im-platform/src/main/java/com/bx/implatform/service/IUserService.java
  13. 75
      im-platform/src/main/java/com/bx/implatform/service/impl/UserServiceImpl.java
  14. 16
      im-platform/src/main/java/com/bx/implatform/session/SessionContext.java
  15. 80
      im-platform/src/main/java/com/bx/implatform/util/JwtUtil.java
  16. 22
      im-platform/src/main/java/com/bx/implatform/vo/LoginVO.java
  17. 38
      im-ui/src/api/httpRequest.js
  18. 10
      im-ui/src/view/Home.vue
  19. 18
      im-ui/src/view/Login.vue

6
im-platform/pom.xml

@ -106,6 +106,12 @@
<artifactId>mybatis-plus-generator</artifactId>
<version>3.3.2</version>
</dependency>
<!-- 引入操作JWT的相关依赖 -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.11.0</version>
</dependency>
</dependencies>
<build>

3
im-platform/src/main/java/com/bx/implatform/ImplatformApp.java

@ -4,13 +4,14 @@ import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Slf4j
@EnableAspectJAutoProxy(exposeProxy = true)
@MapperScan(basePackages = {"com.bx.implatform.mapper"})
@SpringBootApplication
@SpringBootApplication(exclude= {SecurityAutoConfiguration.class })// 禁用secrity
public class ImplatformApp {
public static void main(String[] args) {

36
im-platform/src/main/java/com/bx/implatform/config/MvcConfig.java

@ -0,0 +1,36 @@
package com.bx.implatform.config;
import com.bx.implatform.interceptor.AuthInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor())
.addPathPatterns("/**")
.excludePathPatterns( "/image/upload","/login","/logout","/register","/refreshToken",
"/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**");
}
@Bean
public AuthInterceptor authInterceptor() {
return new AuthInterceptor();
}
@Bean
public PasswordEncoder passwordEncoder(){
// 使用BCrypt加密密码
return new BCryptPasswordEncoder();
}
}

172
im-platform/src/main/java/com/bx/implatform/config/WebSecurityConfg.java

@ -1,172 +0,0 @@
package com.bx.implatform.config;
import com.alibaba.fastjson.JSON;
import com.bx.implatform.enums.ResultCode;
import com.bx.implatform.result.Result;
import com.bx.implatform.result.ResultUtils;
import com.bx.implatform.service.IUserService;
import com.bx.implatform.session.UserSession;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.*;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import java.io.PrintWriter;
/*
* SpringSecurity安全框架配置
*
* @Author Blue
* @Date 2022/10/21
*/
@Slf4j
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class WebSecurityConfg extends WebSecurityConfigurerAdapter {
@Qualifier("securityUserDetailsServiceImpl")
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private IUserService userService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/image/upload","/login","/logout","/register","/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**")
.permitAll()
.anyRequest() //任何其它请求
.authenticated() //都需要身份认证
.and()
// 登录配置表单认证方式
.formLogin()
.usernameParameter("username")//设置登录账号参数,与表单参数一致
.passwordParameter("password")//设置登录密码参数,与表单参数一致
.loginProcessingUrl("/login")//配置默认登录入口
.successHandler(successHandler())
.failureHandler(failureHandler())
.and()
// 注销
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(logoutHandler())
.permitAll()
.and()
// session管理
.sessionManagement()
.and()
// 禁用跨站csrf攻击防御
.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(entryPoint());
}
@Bean
AuthenticationFailureHandler failureHandler(){
return (request, response, exception) -> {
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
Result result = ResultUtils.error(ResultCode.LOGIN_ERROR,exception.getMessage());
if (exception instanceof LockedException) {
result =ResultUtils.error(ResultCode.LOGIN_ERROR,"账户被锁定,请联系管理员!");
} else if (exception instanceof CredentialsExpiredException) {
result = ResultUtils.error(ResultCode.LOGIN_ERROR,"密码过期,请联系管理员!");
} else if (exception instanceof AccountExpiredException) {
result =ResultUtils.error(ResultCode.LOGIN_ERROR,"账户过期,请联系管理员!");
} else if (exception instanceof DisabledException) {
result = ResultUtils.error(ResultCode.LOGIN_ERROR,"账户被禁用,请联系管理员!");
} else if (exception instanceof BadCredentialsException) {
result =ResultUtils.error(ResultCode.LOGIN_ERROR,"用户名或者密码输入错误,请重新输入!");
}
out.write(new ObjectMapper().writeValueAsString(result));
out.flush();
out.close();
};
}
@Bean
AuthenticationSuccessHandler successHandler(){
return (request, response, authentication) -> {
User useDetail = (User)authentication.getPrincipal();
String strJson = useDetail.getUsername();
UserSession userSession = JSON.parseObject(strJson,UserSession.class);
log.info("用户 '{}' 登录,id:{},昵称:{}",userSession.getUserName(),userSession.getId(),userSession.getNickName());
// 响应
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
Result result = ResultUtils.success();
out.write(new ObjectMapper().writeValueAsString(result));
out.flush();
out.close();
};
}
@Bean
LogoutSuccessHandler logoutHandler(){
return (request, response, authentication) -> {
User useDetail = (User)authentication.getPrincipal();
String strJson = useDetail.getUsername();
UserSession userSession = JSON.parseObject(strJson,UserSession.class);
log.info("用户 '{}' 退出,id:{},昵称:{}",userSession.getUserName(),userSession.getId(),userSession.getNickName());
// 响应
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
Result result = ResultUtils.success();
out.write(new ObjectMapper().writeValueAsString(result));
out.flush();
out.close();
};
}
@Bean
AuthenticationEntryPoint entryPoint(){
return (request, response, exception) -> {
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
Result result = ResultUtils.error(ResultCode.NO_LOGIN);
out.write(new ObjectMapper().writeValueAsString(result));
out.flush();
out.close();
};
}
@Bean
public PasswordEncoder passwordEncoder(){
// 使用BCrypt加密密码
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
}

8
im-platform/src/main/java/com/bx/implatform/contant/Constant.java

@ -8,5 +8,13 @@ public class Constant {
public static final long MAX_FILE_SIZE = 10*1024*1024;
// 群聊最大人数
public static final long MAX_GROUP_MEMBER = 500;
// accessToken 过期时间(1小时)
public static final Integer ACCESS_TOKEN_EXPIRE = 30 * 60;
// refreshToken 过期时间(7天)
public static final Integer REFRESH_TOKEN_EXPIRE = 7 * 24 * 60 * 60 ;
// accessToken 加密秘钥
public static final String ACCESS_TOKEN_SECRET = "MIIBIjANBgkq";
// refreshToken 加密秘钥
public static final String REFRESH_TOKEN_SECRET = "IKDiqVmn0VFU";
}

48
im-platform/src/main/java/com/bx/implatform/controller/LoginController.java

@ -0,0 +1,48 @@
package com.bx.implatform.controller;
import com.bx.implatform.result.Result;
import com.bx.implatform.result.ResultUtils;
import com.bx.implatform.service.IUserService;
import com.bx.implatform.dto.LoginDTO;
import com.bx.implatform.dto.RegisterDTO;
import com.bx.implatform.vo.LoginVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@Api(tags = "用户登录和注册")
@RestController
public class LoginController {
@Autowired
private IUserService userService;
@PostMapping("/login")
@ApiOperation(value = "用户注册",notes="用户注册")
public Result register(@Valid @RequestBody LoginDTO dto){
LoginVO vo = userService.login(dto);
return ResultUtils.success(vo);
}
@PutMapping("/refreshToken")
@ApiOperation(value = "刷新token",notes="用refreshtoken换取新的token")
public Result refreshToken(@RequestHeader("refreshToken")String refreshToken){
LoginVO vo = userService.refreshToken(refreshToken);
return ResultUtils.success(vo);
}
@PostMapping("/register")
@ApiOperation(value = "用户注册",notes="用户注册")
public Result register(@Valid @RequestBody RegisterDTO dto){
userService.register(dto);
return ResultUtils.success();
}
}

32
im-platform/src/main/java/com/bx/implatform/controller/RegisterController.java

@ -1,32 +0,0 @@
package com.bx.implatform.controller;
import com.bx.implatform.result.Result;
import com.bx.implatform.result.ResultUtils;
import com.bx.implatform.service.IUserService;
import com.bx.implatform.vo.RegisterVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
@Api(tags = "用户注册")
@RestController
public class RegisterController {
@Autowired
private IUserService userService;
@PostMapping("/register")
@ApiOperation(value = "用户注册",notes="用户注册")
public Result register(@Valid @RequestBody RegisterVO dto){
userService.register(dto);
return ResultUtils.success();
}
}

22
im-platform/src/main/java/com/bx/implatform/dto/LoginDTO.java

@ -0,0 +1,22 @@
package com.bx.implatform.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotEmpty;
@Data
@ApiModel("用户登录VO")
public class LoginDTO {
//@NotEmpty(message="用户名不可为空")
@ApiModelProperty(value = "用户名")
private String userName;
// @NotEmpty(message="用户密码不可为空")
@ApiModelProperty(value = "用户密码")
private String password;
}

4
im-platform/src/main/java/com/bx/implatform/vo/RegisterVO.java → im-platform/src/main/java/com/bx/implatform/dto/RegisterDTO.java

@ -1,4 +1,4 @@
package com.bx.implatform.vo;
package com.bx.implatform.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ -9,7 +9,7 @@ import javax.validation.constraints.NotEmpty;
@Data
@ApiModel("用户注册VO")
public class RegisterVO {
public class RegisterDTO {
@Length(max = 64,message = "用户名不能大于64字符")
@NotEmpty(message="用户名不可为空")

11
im-platform/src/main/java/com/bx/implatform/enums/ResultCode.java

@ -9,16 +9,11 @@ package com.bx.implatform.enums;
**/
public enum ResultCode {
SUCCESS(200,"成功"),
LOGIN_ERROR(400,"登录异常"),
NO_LOGIN(401,"未登录"),
FORBIDDEN(403,"禁止访问"),
NOT_FIND(404,"无法找到文件"),
NO_LOGIN(400,"未登录"),
INVALID_TOKEN(401,"token已失效"),
PROGRAM_ERROR(500,"系统繁忙,请稍后再试"),
PASSWOR_ERROR(10001,"密码不正确"),
VERITY_CODE_NOT_EXIST(10002,"验证码不存在"),
VERITY_CODE_ERROR(10003,"验证码不正确"),
USERNAME_ALREADY_REGISTER(10004,"该用户名已注册"),
MOBILE_ALREADY_REGISTER(10005,"该手机号码已注册"),
USERNAME_ALREADY_REGISTER(10003,"该用户名已注册"),
;

48
im-platform/src/main/java/com/bx/implatform/interceptor/AuthInterceptor.java

@ -0,0 +1,48 @@
package com.bx.implatform.interceptor;
import com.alibaba.fastjson.JSON;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.bx.implatform.contant.Constant;
import com.bx.implatform.enums.ResultCode;
import com.bx.implatform.exception.GlobalException;
import com.bx.implatform.session.UserSession;
import com.bx.implatform.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
;
@Slf4j
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//如果不是映射到方法直接通过
if (!(handler instanceof HandlerMethod)) {
return true;
}
//从 http 请求头中取出 token
String token = request.getHeader("accessToken");
if (token == null) {
log.error("未登陆,url:{}",request.getRequestURI());
throw new GlobalException(ResultCode.NO_LOGIN);
}
try{
//验证 token
JwtUtil.checkSign(token, Constant.ACCESS_TOKEN_SECRET);
}catch (
JWTVerificationException e) {
log.error("token已失效,url:{}",request.getRequestURI());
throw new GlobalException(ResultCode.INVALID_TOKEN);
}
// 存放session
String strJson = JwtUtil.getInfo(token);
UserSession userSession = JSON.parseObject(strJson,UserSession.class);
request.setAttribute("session",userSession);
return true;
}
}

10
im-platform/src/main/java/com/bx/implatform/service/IUserService.java

@ -2,7 +2,9 @@ package com.bx.implatform.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bx.implatform.entity.User;
import com.bx.implatform.vo.RegisterVO;
import com.bx.implatform.dto.LoginDTO;
import com.bx.implatform.dto.RegisterDTO;
import com.bx.implatform.vo.LoginVO;
import com.bx.implatform.vo.UserVO;
import java.util.List;
@ -10,7 +12,11 @@ import java.util.List;
public interface IUserService extends IService<User> {
void register(RegisterVO registerDTO);
LoginVO login(LoginDTO dto);
LoginVO refreshToken(String refreshToken);
void register(RegisterDTO dto);
User findUserByName(String username);

75
im-platform/src/main/java/com/bx/implatform/service/impl/UserServiceImpl.java

@ -1,8 +1,11 @@
package com.bx.implatform.service.impl;
import com.alibaba.fastjson.JSON;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bx.imcommon.contant.RedisKey;
import com.bx.implatform.contant.Constant;
import com.bx.implatform.entity.Friend;
import com.bx.implatform.entity.GroupMember;
import com.bx.implatform.entity.User;
@ -15,7 +18,10 @@ import com.bx.implatform.service.IUserService;
import com.bx.implatform.session.SessionContext;
import com.bx.implatform.session.UserSession;
import com.bx.implatform.util.BeanUtils;
import com.bx.implatform.vo.RegisterVO;
import com.bx.implatform.util.JwtUtil;
import com.bx.implatform.dto.LoginDTO;
import com.bx.implatform.dto.RegisterDTO;
import com.bx.implatform.vo.LoginVO;
import com.bx.implatform.vo.UserVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@ -28,6 +34,8 @@ import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
import static com.bx.implatform.contant.Constant.REFRESH_TOKEN_SECRET;
@Slf4j
@Service
@ -45,22 +53,77 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IU
@Autowired
private IFriendService friendService;
/**
* 用户登录
*
* @param dto 登录dto
* @return
*/
@Override
public LoginVO login(LoginDTO dto) {
User user = findUserByName(dto.getUserName());
if(null == user){
throw new GlobalException(ResultCode.PROGRAM_ERROR,"用户不存在");
}
if(!passwordEncoder.matches(dto.getPassword(),user.getPassword())){
throw new GlobalException(ResultCode.PASSWOR_ERROR);
}
// 生成token
UserSession session = BeanUtils.copyProperties(user,UserSession.class);
String strJson = JSON.toJSONString(session);
String accessToken = JwtUtil.sign(user.getId(),strJson, Constant.ACCESS_TOKEN_EXPIRE,Constant.ACCESS_TOKEN_SECRET);
String refreshToken = JwtUtil.sign(user.getId(),strJson, Constant.REFRESH_TOKEN_EXPIRE, REFRESH_TOKEN_SECRET);
LoginVO vo = new LoginVO();
vo.setAccessToken(accessToken);
vo.setAccessTokenExpiresIn(Constant.ACCESS_TOKEN_EXPIRE);
vo.setRefreshToken(refreshToken);
vo.setRefreshTokenExpiresIn(Constant.REFRESH_TOKEN_EXPIRE);
return vo;
}
/**
* 用refreshToken换取新 token
*
* @param refreshToken
* @return
*/
@Override
public LoginVO refreshToken(String refreshToken) {
try{
//验证 token
JwtUtil.checkSign(refreshToken, REFRESH_TOKEN_SECRET);
String strJson = JwtUtil.getInfo(refreshToken);
Long userId = JwtUtil.getUserId(refreshToken);
String accessToken = JwtUtil.sign(userId,strJson, Constant.ACCESS_TOKEN_EXPIRE,Constant.ACCESS_TOKEN_SECRET);
String newRefreshToken = JwtUtil.sign(userId,strJson, Constant.REFRESH_TOKEN_EXPIRE, REFRESH_TOKEN_SECRET);
LoginVO vo =new LoginVO();
vo.setAccessToken(accessToken);
vo.setAccessTokenExpiresIn(Constant.ACCESS_TOKEN_EXPIRE);
vo.setRefreshToken(newRefreshToken);
vo.setRefreshTokenExpiresIn(Constant.REFRESH_TOKEN_EXPIRE);
return vo;
}catch (JWTVerificationException e) {
throw new GlobalException("refreshToken已失效");
}
}
/**
* 用户注册
*
* @param vo 注册vo
* @param dto 注册dto
* @return
*/
@Override
public void register(RegisterVO vo) {
User user = findUserByName(vo.getUserName());
public void register(RegisterDTO dto) {
User user = findUserByName(dto.getUserName());
if(null != user){
throw new GlobalException(ResultCode.USERNAME_ALREADY_REGISTER);
}
user = BeanUtils.copyProperties(vo,User.class);
user = BeanUtils.copyProperties(dto,User.class);
user.setPassword(passwordEncoder.encode(user.getPassword()));
this.save(user);
log.info("注册用户,用户id:{},用户名:{},昵称:{}",user.getId(),vo.getUserName(),vo.getNickName());
log.info("注册用户,用户id:{},用户名:{},昵称:{}",user.getId(),dto.getUserName(),dto.getNickName());
}
/**

16
im-platform/src/main/java/com/bx/implatform/session/SessionContext.java

@ -1,8 +1,9 @@
package com.bx.implatform.session;
import com.alibaba.fastjson.JSON;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/*
* @Description
@ -13,11 +14,12 @@ public class SessionContext {
public static UserSession getSession(){
User useDetail = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String strJson = useDetail.getUsername();
UserSession userSession = JSON.parseObject(strJson,UserSession.class);
// 从请求上下文里获取Request对象
ServletRequestAttributes requestAttributes = ServletRequestAttributes.class.
cast(RequestContextHolder.getRequestAttributes());
HttpServletRequest request = requestAttributes.getRequest();
UserSession userSession = (UserSession) request.getAttribute("session");
return userSession;
}
}

80
im-platform/src/main/java/com/bx/implatform/util/JwtUtil.java

@ -0,0 +1,80 @@
package com.bx.implatform.util;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import java.util.Date;
public class JwtUtil {
/**
* 生成jwt字符串30分钟后过期 JWT(json web token)
* @param userId
* @param info
* @param expireIn
* @param secret
* @return
* */
public static String sign(Long userId, String info,long expireIn,String secret) {
try {
Date date = new Date(System.currentTimeMillis() + expireIn*1000);
Algorithm algorithm = Algorithm.HMAC256(secret);
return JWT.create()
//将userId保存到token里面
.withAudience(userId.toString())
//存放自定义数据
.withClaim("info", info)
//五分钟后token过期
.withExpiresAt(date)
//token的密钥
.sign(algorithm);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 根据token获取userId
* @param token
* @return
* */
public static Long getUserId(String token) {
try {
String userId = JWT.decode(token).getAudience().get(0);
return Long.parseLong(userId);
}catch (JWTDecodeException e) {
return null;
}
}
/**
* 根据token获取自定义数据info
* @param token
* @return
* */
public static String getInfo(String token) {
try {
return JWT.decode(token).getClaim("info").asString();
}catch (JWTDecodeException e) {
return null;
}
}
/**
* 校验token
* @param token
* @param secret
* @return
* */
public static boolean checkSign(String token,String secret) {
Algorithm algorithm = Algorithm.HMAC256(secret);
JWTVerifier verifier = JWT.require(algorithm)
//.withClaim("username, username)
.build();
verifier.verify(token);
return true;
}
}

22
im-platform/src/main/java/com/bx/implatform/vo/LoginVO.java

@ -0,0 +1,22 @@
package com.bx.implatform.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("用户登录VO")
public class LoginVO {
@ApiModelProperty(value = "每次请求都必须在header中携带accessToken")
private String accessToken;
@ApiModelProperty(value = "accessToken过期时间(秒)")
private Integer accessTokenExpiresIn;
@ApiModelProperty(value = "accessToken过期后,通过refreshToken换取新的token")
private String refreshToken;
@ApiModelProperty(value = "refreshToken过期时间(秒)")
private Integer refreshTokenExpiresIn;
}

38
im-ui/src/api/httpRequest.js

@ -1,6 +1,8 @@
import axios from 'axios'
import router from '@/router'
import {Message} from 'element-ui'
import {
Message
} from 'element-ui'
const http = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
@ -15,7 +17,10 @@ const http = axios.create({
* 请求拦截
*/
http.interceptors.request.use(config => {
// todo 请求头带上token
let accessToken = sessionStorage.getItem("accessToken");
if (accessToken) {
config.headers.accessToken = encodeURIComponent(accessToken);
}
return config
}, error => {
return Promise.reject(error)
@ -24,9 +29,32 @@ http.interceptors.request.use(config => {
/**
* 响应拦截
*/
http.interceptors.response.use(response => {
http.interceptors.response.use(async response => {
if (response.data.code == 200) {
return response.data.data;
} else if (response.data.code == 400) {
router.replace("/login");
} else if (response.data.code == 401) {
console.log("token失效,尝试重新获取")
let refreshToken = sessionStorage.getItem("refreshToken");
if (!refreshToken) {
router.replace("/login");
}
// 发送请求, 进行刷新token操作, 获取新的token
const data = await http({
method: 'put',
url: '/refreshToken',
headers: {
refreshToken: refreshToken
}
})
// 保存token
sessionStorage.setItem("accessToken", data.accessToken);
sessionStorage.setItem("refreshToken", data.refreshToken);
// 这里需要把headers清掉,否则请求时会报错,原因暂不详...
response.config.headers=undefined;
// 重新发送刚才的请求
return http(response.config)
} else {
Message({
message: response.data.message,
@ -34,10 +62,6 @@ http.interceptors.response.use(response => {
duration: 1500,
customClass: 'element-error-message-zindex'
})
if (response.data.code == 401) {
router.replace("/login");
}
return Promise.reject(response.data)
}
}, error => {

10
im-ui/src/view/Home.vue

@ -190,13 +190,9 @@
this.playAudioTip();
},
handleExit() {
this.$http({
url: "/logout",
method: 'get'
}).then(() => {
this.$wsApi.closeWebSocket();
location.href = "/";
})
this.$wsApi.closeWebSocket();
sessionStorage.removeItem("token");
location.href = "/";
},
playAudioTip(){
let audio = new Audio();

18
im-ui/src/view/Login.vue

@ -2,8 +2,8 @@
<div class="login-view" >
<el-form :model="loginForm" status-icon :rules="rules" ref="loginForm" label-width="60px" class="web-ruleForm" @keyup.enter.native="submitForm('loginForm')">
<div class="login-brand">欢迎登陆</div>
<el-form-item label="用户名" prop="username">
<el-input type="username" v-model="loginForm.username" autocomplete="off"></el-input>
<el-form-item label="用户名" prop="userName">
<el-input type="userName" v-model="loginForm.userName" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
@ -42,11 +42,11 @@
};
return {
loginForm: {
username: '',
userName: '',
password: ''
},
rules: {
username: [{
userName: [{
validator: checkUsername,
trigger: 'blur'
}],
@ -64,11 +64,15 @@
this.$http({
url: "/login",
method: 'post',
params: this.loginForm
data: this.loginForm
})
.then((data) => {
this.setCookie('username',this.loginForm.username);
// cookie()
this.setCookie('username',this.loginForm.userName);
this.setCookie('password',this.loginForm.password);
// token
sessionStorage.setItem("accessToken",data.accessToken);
sessionStorage.setItem("refreshToken",data.refreshToken);
this.$message.success("登陆成功");
this.$router.push("/home/chat");
})
@ -105,7 +109,7 @@
}
},
mounted() {
this.loginForm.username = this.getCookie("username");
this.loginForm.userName = this.getCookie("username");
// cookie便
this.loginForm.password = this.getCookie("password");
}

Loading…
Cancel
Save