# token:
## 1、定义
token:服务端生成的一串字符串,可以解决频繁登录的问题
它作为客户端进行请求的一个令牌:
第一次登录后,服务器生成一个token返回给客户端;
客户端只需要带上token来请求数据即可,无需再次带上用户名和密码
## 2、目的
为了减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮
## 3、使用(后端)
生成token的插件:jsonwebtoken
下载:cnpm install jsonwebtoken --save
@Component
/*@component (把普通pojo实例化到spring容器中,相当于配置文件中的 )
泛指各种组件,就是说当我们的类不属于各种归类的时候(不属于@Controller、@Services等的时候),我们就
可以使用@Component来标注这个类。*/
@Slf4j
public class TokenUtils{
private static AdminService static AdminService;
@Resource
private AdminService adminService;
/*@Resource默认按照名字装配Bean,即会按照name属性的值来找到具有相同id的Bean Definition 并注入。
如果@Resource没有指定name属性,则会根据这个将要被注入的属性的名字来进行Bean装配。这段话有点绕口,下面结合例子来展示。可以查看下面链接博主的文章。
//@Resource的name属性的值与Person类的@Component的value值相对应【都是 renlei】,所以可以进行装配
/*@Reource 没有指定name的值,所以容器会拿这个p1变量的名字去Bean池子中查找id为renlei的bean并装配到这个renlei变量中。装配成功*/
/*@Reource 没有指定name的值,所以容器会拿这个p1变量的名字去Bean池子中查找id为p1的bean并装配到这个p1变量中。如果找不到,就按照类型来进行装配,都是Person类,所以装配成功*/
@PostConstruct
public void setUserService(){
staticAdminService=adminService;
}
/*加上该注解的方法会在项目启动的时候执行,可以理解为Spring容器在对类自动初始化全局的单一实例的过程中,执行完一个Bean的构造方法后会执行该Bean的@PostConstruct方法(如果有),然后初始化下一个Bean。可
@Configuration配置spring并启动spring容器
1.2、@Configuration启动容器+@Bean注册Bean
1.3、@Configuration启动容器+@Component注册Bean
被@PostConstruct修饰的方法会在服务器加载Servle的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行*/
/**
*生成token
*
*@return
*/
public static String genToken(StringadminId,Stringsign){
return JWT.create().withAudience(adminId)//将userid保存到token里面,作为载荷
.withExpiresAt(DateUtil.offsetHour(newDate(),2))//2小时后token过期
.sign(Algorithm.HMAC256(sign));//以password作为token的密钥
}
/**
*获取当前登录的用户信息
*
*@return user对象
*/admin?token=xxxx
*/
public static Admin getCurrentAdmin(){
Stringtoken=null;
try{
HttpServletRequestrequest=((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
token=request.getHeader("token");
if(StrUtil.isNotBlank(token)){
token=request.getParameter("token");
}
if(StrUtil.isBlank(token)){
log.error("获取当前登录的token失败,token:{}",token);
return null;
}
String adminId=JWT.decode(token).getAudience().get(0);
return staticAdminService.getById(Integer.valueOf(adminId));
}catch(Exceptione){
log.error("获取当前登录的管理员信息失败,token={}",token,e);
return null;
}
}
}
# WebConfig:
作用:添加拦截规则
@Configuration
public class WebConfig implements WebMvcConfigurer{
/*@Configuration配置spring并启动spring容器
@Configuration启动容器+@Bean注册Bean
@Configuration启动容器+@Component注册Bean*/
@Autowired
JwtInterceptor jwtInterceptor;
/*@Autowired是默认按照类型装配Bean,当需要用名称装配时,可以在@Autowired后面使用@Qualifier注解指定name属性,来告知容器加载哪个bean*/
@Override
public void configurePathMatch(PathMatchConfigurerconfigurer){
//指定controller统一的接口前缀
configurer.addPathPrefix("/api",clazz->clazz.isAnnotationPresent(RestController.class));
}
//加自定义拦截器JwtInterceptor,设置拦截规则
@Override
public void addInterceptors(InterceptorRegistryregistry){
registry.addInterceptor(jwtInterceptor).addPathPatterns("/api/**").excludePathPatterns("/api/login/**");
}
}
JwtInterceptor:
是拦截规则
@Component
@Slf4j
public class JwtInterceptorimplementsHandlerInterceptor{
private static final String ERROR_CODE_401="401";
@Autowired
private AdminService adminService;
@Override
public boolean preHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler){
String token=request.getHeader("token");
if(StrUtil.isBlank(token)){
token=request.getParameter("token");
}
//执行认证
if(StrUtil.isBlank(token)){
throw new ServiceException(ERROR_CODE_401,"无token,请重新登录");
}
//获取token中的adminId
String adminId;
Admin admin;
try{
adminId=JWT.decode(token).getAudience().get(0);
//根据token中的userid查询数据库
admin=adminService.getById(Integer.parseInt(adminId));
}catch(Exceptione){
String errMsg="token验证失败,请重新登录";
log.error(errMsg+",token="+token,e);
throw new ServiceException(ERROR_CODE_401,errMsg);
}
if(admin==null){
throw new ServiceException(ERROR_CODE_401,"用户不存在,请重新登录");
}
try{
//用户密码加签验证token
JWTVerifierjwtVerifier=JWT.require(Algorithm.HMAC256(admin.getPassword())).build();
jwtVerifier.verify(token);//验证token
}catch(JWTVerificationExceptione){
throw new ServiceException(ERROR_CODE_401,"token验证失败,请重新登录");
}
return true;
}
}
# CorsConfig:
在开发接口的过程中,最令人头疼一件事就是接口项目有跨域问题,导致前端ajax等访问受限,
所以在搭建一个接口项目之前首先要解决接口的可能跨域问题,CorsConfig是用来解决跨域问题的
@Configuration
public class CorsConfig{
@Bean
public CorsFilter corsFilter(){
UrlBasedCorsConfigurationSource source=newUrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration=newCorsConfiguration();
corsConfiguration.addAllowedOrigin("*");//1设置访问源地址
corsConfiguration.addAllowedHeader("*");//2设置访问源请求头
corsConfiguration.addAllowedMethod("*");//3设置访问源请求方法
source.registerCorsConfiguration("/**",corsConfiguration);//4对接口配置跨域设置
return new CorsFilter(source);
}
}
源代码可以查看:SpringBoot集成JWT(极简版)_springboot集成jwt 程序员青戈_程序员青戈的博客-CSDN博客