2.4、添加controller
import com.alibaba.nacos.shaded.com.google.gson.Gson; import com.xxxx.authorityservice.config.JwtConfig; import com.xxxx.commonapi.dto.ResultDTO; import com.xxxx.commonapi.dto.TokenDTO; import com.xxxx.commonapi.entity.UserInfo; import com.xxxx.commonapi.http.HttpResultGenerator; import com.xxxx.commonapi.http.HttpStatusEnum; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Map; @RestController @RequestMapping("/auth") public class AuthController { @Autowired private JwtConfig jwtConfig; /** * 登录 */ @PostMapping("/login") public ResultDTO login(@RequestBody UserInfo userInfo){ String token = jwtConfig.createToken(new Gson().toJson(userInfo)); Map<String, String> map = new HashMap(); map.put("token",token); return HttpResultGenerator.success(HttpStatusEnum.SUCCESS,map); } /** * token是否正确 */ @PostMapping("/isRight") public ResultDTO isRight(){ return HttpResultGenerator.success(HttpStatusEnum.SUCCESS,"成功!"); } /** * token解密 */ @PostMapping("/getUserMessageByToken") public ResultDTO getUserMessageByToken(HttpServletRequest request){ String name = jwtConfig.getUserNameFromToken(request.getHeader("token")); return HttpResultGenerator.success(HttpStatusEnum.SUCCESS,name); } /** * token是否过期 */ @PostMapping("/isTokenExpiration") public Boolean isTokenExpiration(@RequestBody TokenDTO tokenDTO){ return this.jwtConfig.isTokenExpired(this.jwtConfig.getExpirationDateFromToken(tokenDTO.getToken())); } }
3、gateway工程改造
3.1、修改配置文件
这里是在nacos配置中心写的配置文件
添加下图红框内容
- id: auth-service_routh #路由 id,没有固定规则,但唯一,建议与服务名对应 uri: lb://authority-service #匹配后提供服务的路由地址 predicates: #以下是断言条件,必auth选全部符合条件 - Path=/auth/** #断言,路径匹配 注意:Path 中 P 为大写 - Method=GET,POST #只能时 GET,POST 请求时,才能访问
3.2、新建AuthService接口
import com.xxxx.commonapi.dto.TokenDTO; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; /** * @author kelvin * @Date 2023/6/8 - 10:09 */ @FeignClient(value = "authority-service") public interface AuthService { @PostMapping("/auth/isTokenExpiration") public Boolean validateToken(@RequestBody TokenDTO tokenDTO); }
注意事项:
接口中的value值必须与服务名完全相同!
方法中的参数必须与authority-service服务的/auth/isTokenExpiration接口的参数对应上,最好使用RequestBody接收,否则参数过长可能导致失败!
3.3、新建filter目录,新建DrfGlobalFilter全局拦截器
import com.alibaba.nacos.api.utils.StringUtils; import com.alibaba.nacos.shaded.com.google.gson.Gson; import com.xxxx.commonapi.dto.TokenDTO; import com.xxxx.commonapi.http.HttpResultGenerator; import com.xxxx.commonapi.http.HttpStatusEnum; import com.xxxx.gatewayservice.service.AuthService; import lombok.SneakyThrows; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import javax.servlet.http.HttpServletResponse; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @Component public class DrfGlobalFilter implements GlobalFilter, Ordered { private final AuthService authService; private ExecutorService executorService; public DrfGlobalFilter(AuthService authService) { this.authService = authService; this.executorService = Executors.newFixedThreadPool(5); } @Bean @ConditionalOnMissingBean public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) { return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList())); } @SneakyThrows @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); //如果登录请求,不用验证token String path = request.getURI().getPath(); if(!path.contains("login")){ HttpHeaders headers = request.getHeaders(); String token = headers.getFirst("token"); //token为空表示没有登录,否则已经登录 if(StringUtils.isBlank(token)){ ServerHttpResponse response = exchange.getResponse(); response.setStatusCode(HttpStatus.UNAUTHORIZED); return response.setComplete(); }else{ TokenDTO tokenDTO = new TokenDTO(); tokenDTO.setToken(token); Boolean f = authService.validateToken(tokenDTO); if(f){ ServerHttpResponse response = exchange.getResponse(); response.setStatusCode(HttpStatus.UNAUTHORIZED); HttpServletResponse response1 = (HttpServletResponse) response; response1.getWriter().write(new Gson().toJson(HttpResultGenerator.fail(HttpStatusEnum.REQUEST_METHOD_SUPPORT_ERROR))); return response.setComplete(); } } } return chain.filter(exchange); } @Override public int getOrder() { return 0; } }
4、Postman测试
5、创建vue3项目,与后台JWT鉴权交互
5.1、进入cmd界面,进入到存放前端项目的文件夹
5.2、安装vue脚手架vue-cli3
cnpm install @vue/cli -g 注:安装过的可以不用再安装
安装后查看vue的版本
vue -V
5.3、创建Vue项目,项目名称不支持特殊字符也不支持驼峰命名
vue create 项目名称
选择vue3
5.4、vue项目引入Element-Plus
打开终端进入项目文件夹
5.4.1、安装element-plus
cnpm install element-plus --save
安装后在package.json中可以看到element-plus的版本
5.4.2、在main.js中导入element-plus并使用
import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' app.use(ElementPlus)