登录接口
@ApiOperation("登录接口")
@PostMapping("/auth")
public Result toLogin(@RequestBody InfoUser users){
if (users.getUsername() == null || users.getPassword()==null) {
return Result.error("用户名和密码不能为空");
}
InfoUser users1 = loginService.toLogin(users);
if(users1==null){
return Result.error("用户或密码错误");
}else {
//身份验证成功
String token = TokenUtils.token(users.getUsername(), users.getPassword());
if (token != null) {
Map<String,Object> map = new HashMap<>();
map.put("userInfo",users1);
map.put("token",token);
return Result.success(map);
}
}
return Result.success(users1);
}
拦截器,拦截除了登录请求以外的所有请求
import com.alibaba.fastjson.JSONObject;
import com.dfdt.util.PageUtils;
import com.dfdt.util.Result;
import com.dfdt.util.ResultEnum;
import com.dfdt.util.TokenUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class TokenInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
response.setCharacterEncoding("UTF-8");
//从前端传的request中获取token.需要与前端确认传的key是啥,我的是Authorization
String token = request.getHeader("Authorization");
if (null != token) {
//判断token是否通过验证
Result result= TokenUtils.verify(token);
if (result.getCode().equals(200)) {
return true;
}else {
response.getWriter().write(JSONObject.toJSONString(result));
return false;
}
}
Result<Object> error = Result.error(ResultEnum.TOKEN_ERROR);
response.getWriter().write(JSONObject.toJSONString(error));
return false;
}
}
写好的拦截器需要通过这里添加注册才能生效
import com.dfdt.entity.ReadAppliationYml;
import com.dfdt.filter.TokenRefreshFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class LoginAdapter implements WebMvcConfigurer {
//解决跨域问题
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedHeaders("Content-Type","X-Requested-With","accept,Origin","Access-Control-Request-Method","Access-Control-Request-Headers","token")
.allowedMethods("*")
.allowedOrigins("*")
//是否允许使用cookie
.allowCredentials(true);
}
@Autowired
private TokenInterceptor tokenInterceptor ;
// 这个方法是用来配置静态资源的,比如html,js,css,等等
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String mediaUploadPath = new ReadAppliationYml().getMediaUploadPath();
String imageUploadPath = new ReadAppliationYml().getImageUploadPath();
registry.addResourceHandler("/Media/**").addResourceLocations("file:/"+mediaUploadPath);
registry.addResourceHandler("/Image/**").addResourceLocations("file:/"+imageUploadPath);
WebMvcConfigurer.super.addResourceHandlers(registry);
}
// 这个方法用来注册拦截器,我们自己写好的拦截器需要通过这里添加注册才能生效
@Override
public void addInterceptors(InterceptorRegistry registry) {
System.out.println("进入拦截器");
//需要放行的请求
String[] pattrens = new String[]{"/**/auth","/**/*.html","/**/swagger-resources/**",
"/**/webjars/**","/**/v2/**",
"/**/swagger-ui.html"};
//addPathPatterns是表明拦截哪些请求
//excludePathPatterns是对哪些请求不做拦截
registry.addInterceptor(tokenInterceptor).addPathPatterns("/**")
.excludePathPatterns(pattrens);
}
}
导包
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.2.0</version>
</dependency>
token工具类
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @desc 使用token验证用户是否登录
**/
public class TokenUtils {
//设置过期时间
private static final long EXPIRE_DATE = 60 * 60 * 1000 * 24; //一天
// private static final long EXPIRE_DATE = 60 * 1000;//一分钟
//token秘钥
private static final String TOKEN_SECRET = "1234564654651313221321";//密钥自己设定一个
/**
* 生成签名,
*
* @param username
* @param password
* @return
*/
public static String token(String username, String password) {
String token = "";
try {
//过期时间
Date date = new Date(System.currentTimeMillis() + EXPIRE_DATE);
//秘钥及加密算法
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
//设置头部信息
Map<String, Object> header = new HashMap<>();
header.put("typ", "JWT");
header.put("alg", "HS256");
//携带username,password信息,生成签名
token = JWT.create()
.withHeader(header)
.withClaim("username", username)
.withClaim("password", password).withExpiresAt(date)
.sign(algorithm);
} catch (Exception e) {
e.printStackTrace();
return null;
}
return token;
}
// public static boolean verify(String token) {
// /**
// * @desc 验证token,通过返回true
// * @params [token]需要校验的串
// **/
// try {
// Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
// JWTVerifier verifier = JWT.require(algorithm).build();
// DecodedJWT jwt = verifier.verify(token);
// return true;
// }catch (TokenExpiredException e1){
// //token过期
// e1.printStackTrace();
// return false;
// }catch (Exception e) {
// //token没有验证通过
// e.printStackTrace();
// return false;
// }
// }
public static Result verify(String token) {
/**
* @desc 验证token,通过返回true
* @params [token]需要校验的串
**/
try {
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
JWTVerifier verifier = JWT.require(algorithm).build();
DecodedJWT jwt = verifier.verify(token);
return Result.success(null);
} catch (TokenExpiredException e1){
//TokenExpiredException 该异常 为token 过期
// e1.printStackTrace();
//可以返回自己设定的token过期的code
return Result.error(ResultEnum.TOKEN_PAST);
}catch (Exception e) {
//token 验证失败
// e.printStackTrace();
return Result.error(ResultEnum.TOKEN_ERROR);
}
}
/**
* 我们可以将一些常用的信息放入token中,比如用户登陆信息,方便我们的使用
* 获得token中的信息无需secret解密也能获得
*/
public static String getUsername(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("username").asString();
} catch (Exception e) {
return null;
}
}
}
接口返回实体
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import org.apache.poi.ss.formula.functions.Count;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
/**
* 接口返回对象实体
*/
@Data
public final class Result<T> implements Serializable {
private static final Logger logger = LoggerFactory.getLogger(Result.class);
private static final long serialVersionUID = 1L;
public static final String SUCCESSFUL_CODE = "000000";
public static final String SUCCESSFUL_MESG = "处理成功";
/**
* 错误码
*/
private Integer code = 0;
/**
* 错误信息
*/
private String msg = null;
private Integer count = 0;
/**
* 返回结果实体
*/
private T data = null;
public Result() {
}
public Result(Integer code, String msg, Integer count, T data) {
this.code = code;
this.msg = msg;
this.count = count;
this.data = data;
}
public Result(int code, String msg) {
this.code = code;
this.msg = msg;
}
public Result(ResultEnum resultEnum) {
this.code = resultEnum.getCode();
this.msg = resultEnum.getDesc();
}
public Result(ResultEnum resultEnum, T data) {
this.code = resultEnum.getCode();
this.msg = resultEnum.getDesc();
this.data = data;
}
public static <T> Result<T> error(String msg) {
logger.debug("返回错误:code={}, msg={}", ResultEnum.ERROR.getCode(), msg);
return new Result<T>(ResultEnum.ERROR.getCode(), msg, null);
}
public static <T> Result<T> error(ResultEnum resultEnum) {
logger.debug("返回错误:code={}, msg={}", resultEnum.getCode(), resultEnum.getDesc());
return new Result<T>(resultEnum.getCode(), resultEnum.getDesc(), null);
}
public static <T> Result<T> error(int code, String msg) {
logger.debug("返回错误:code={}, msg={}", code, msg);
return new Result<T>(code, msg, null);
}
public static <T> Result<T> success(T data) {
return new Result<T>(ResultEnum.SUCCESS.getCode(), "响应成功", 0,data);
}
public static <T> Result<T> success(T data, Integer count) {
return new Result<T>(ResultEnum.SUCCESS.getCode(), "响应成功", count,data);
}
/**
* 成功code=000000
*
* @return true/false
*/
@JsonIgnore
public boolean isSuccess() {
return SUCCESSFUL_CODE.equals(this.code);
}
/**
* 失败
*
* @return true/false
*/
@JsonIgnore
public boolean isFail() {
return !isSuccess();
}
public Result(Integer code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public static Logger getLogger() {
return logger;
}
public static long getSerialVersionUID() {
return serialVersionUID;
}
public static String getSuccessfulCode() {
return SUCCESSFUL_CODE;
}
public static String getSuccessfulMesg() {
return SUCCESSFUL_MESG;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
枚举类 code和msg
public enum ResultEnum {
// 成功
SUCCESS(200, "成功"),
// token异常
TOKEN_PAST(301, "token过期"), TOKEN_ERROR(302, "token异常"),
// 登录异常
LOGIN_ERROR(303, "登录异常"), REMOTE_ERROR(304, "异地登录"),
MENU_PAST(305, "菜单过期"), MENU_NO(306, "没此权限,请联系管理员!"),
// 课程异常,4开头
COURSE_SAVE_FAIL(403, "添加失败"), COURSE_UPDATE_FAIL(404, "更新失败"), COURSE_DELETE_FAIL(405, "删除失败"),
//
COLLECTION(406, "已收藏"), USER_ADVICE(406, "保存建议失败,不能重复提建议"), COURSE_AUDIT_FAIL(407, "审核失败"),
// 用户异常,5开头
LECTURER_REQUISITION_REGISTERED(501, "申请失败!该手机没注册,请先注册账号"), LECTURER_REQUISITION_WAIT(502, "申请失败!该账号已提交申请入驻成为讲师,待审核中,在7个工作日内会有相关人员与您联系确认"), LECTURER_REQUISITION_YET(503, "申请失败!该账号已成为讲师,请直接登录"),
//
USER_SAVE_FAIL(504, "添加失败"), USER_UPDATE_FAIL(505, "更新失败"), LECTURER_REQUISITION_FAIL(506, "申请失败!该账号已提交申请入驻成为讲师,审核不通过,请联系平台管理员"), USER_LECTURER_AUDIT(507, "审核失败"), USER_SEND_FAIL(508, "发送失败"),
USER_DELETE_FAIL(509, "删除失败"),
// 系統异常,6开头
SYSTEM_SAVE_FAIL(601, "添加失败"), SYSTEM_UPDATE_FAIL(602, "更新失败"), SYSTEM_DELETE_FAIL(603, "删除失败"),
// 错误
ERROR(999, "错误");
private Integer code;
private String desc;
ResultEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
ResultEnum() {
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}