Spring Cloud Gateway 使用JWT工具类做用户登录校验功能
1.JWT测试
/** *@Auther:csp1999 *@Date:2021/01/24/19:29 *@Description:JWT测试 */ publicclassJwtTest{ /** *创建Jwt令牌: * *JWT=头部Header+载荷playload+签名signature */ @Test publicvoidtestCreateJwt(){ //构建jwt令牌 //1.头部Header:描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等 JwtBuilderbuilder=Jwts.builder() .setId("8989")//设置令牌唯一编号 .setIssuer("csp1999")//设置令牌颁发者 .setSubject("JWT加密测试")//设置令牌主题可以是JSON数据 .setIssuedAt(newDate())//设置令牌签发日期 .setExpiration(newDate(System.currentTimeMillis()+1000*60*3));//设置令牌过期时间3分钟 //2.自定义载荷playload:存放有效信息的地方 MapuserInfo=newHashMap<>(); userInfo.put("username","csp"); userInfo.put("password","123456"); userInfo.put("school","河南科技大学"); userInfo.put("age","22"); //将载荷添加到JWT令牌中 builder.addClaims(userInfo); //3.为令牌设置签名signature builder.signWith(SignatureAlgorithm.HS256,"haust");//设置令牌的签名使用HS256算法,并设置SecretKey密钥(字符串) //构建并返回一个字符串 StringjwtStr=builder.compact(); System.out.println(jwtStr); } /** *解析Jwt令牌数据 */ @Test publicvoidtestParseJwt(){ //jwt字符串 StringjwtStr="eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4OTg5IiwiaXNzIjoiY3NwMTk5OSIsInN1YiI6IkpXVOWKoOWvhua1i-ivlSIsImlhdCI6MTYxMTQ4ODc1MSwiZXhwIjoxNjExNDg4OTMxLCJwYXNzd29yZCI6IjEyMzQ1NiIsInNjaG9vbCI6Iuays-WNl-enkeaKgOWkp-WtpiIsImFnZSI6IjIyIiwidXNlcm5hbWUiOiJjc3AifQ.uH28G9MSHfzaKBAOyr8AdksYLVvy8O5P8g7TORZIUFY"; //解析jwt字符串 Claimsclaims=Jwts.parser(). setSigningKey("haust").//密钥(盐) parseClaimsJws(jwtStr).//要解析的令牌对象 getBody();//获取解析后的结果 //{jti=8989,iss=csp1999,sub=JWT加密测试,iat=1611488751,exp=1611488931,password=123456,school=河南科技大学,age=22,username=csp} System.out.println(claims); } }
2.JWT工具类
/** *@Auther:csp1999 *@Date:2021/01/24/19:29 *@Description:JWT工具类 */ publicclassJwtUtil{ //有效期为 publicstaticfinalLongJWT_TTL=3600000L;//60*60*1000一个小时 //Jwt令牌信息 publicstaticfinalStringJWT_KEY="itcast"; /** *生成令牌 *@paramid *@paramsubject *@paramttlMillis *@return */ publicstaticStringcreateJWT(Stringid,Stringsubject,LongttlMillis){ //指定算法 SignatureAlgorithmsignatureAlgorithm=SignatureAlgorithm.HS256; //当前系统时间 longnowMillis=System.currentTimeMillis(); //令牌签发时间 Datenow=newDate(nowMillis); //如果令牌有效期为null,则默认设置有效期1小时 if(ttlMillis==null){ ttlMillis=JwtUtil.JWT_TTL; } //令牌过期时间设置 longexpMillis=nowMillis+ttlMillis; DateexpDate=newDate(expMillis); //生成秘钥 SecretKeysecretKey=generalKey(); //封装Jwt令牌信息 JwtBuilderbuilder=Jwts.builder() .setId(id)//唯一的ID .setSubject(subject)//主题可以是JSON数据 .setIssuer("admin")//签发者 .setIssuedAt(now)//签发时间 .signWith(signatureAlgorithm,secretKey)//签名算法以及密匙 .setExpiration(expDate);//设置过期时间 returnbuilder.compact(); } /** *生成加密secretKey * *@return */ publicstaticSecretKeygeneralKey(){ byte[]encodedKey=Base64.getEncoder().encode(JwtUtil.JWT_KEY.getBytes()); SecretKeykey=newSecretKeySpec(encodedKey,0,encodedKey.length,"AES"); returnkey; } /** *解析令牌数据 * *@paramjwt *@return *@throwsException */ publicstaticClaimsparseJWT(Stringjwt)throwsException{ SecretKeysecretKey=generalKey(); returnJwts.parser() .setSigningKey(secretKey) .parseClaimsJws(jwt) .getBody(); } publicstaticvoidmain(String[]args){ Stringjwt=JwtUtil.createJWT("weiyibiaoshi","aaaaaa",null); System.out.println(jwt); try{ Claimsclaims=JwtUtil.parseJWT(jwt); System.out.println(claims); }catch(Exceptione){ e.printStackTrace(); } } }
3.用户登录校验
3.1网关过滤器
/** *@Auther:csp1999 *@Date:2021/01/24/20:17 *@Description:授权过滤器 */ @Component publicclassAuthorizeFilterimplementsGlobalFilter,Ordered{ //令牌头名字 privatestaticfinalStringAUTHORIZE_TOKEN="Authorization"; /** *全局过滤器 * *@paramexchange *@paramchain *@return */ @Override publicMonofilter(ServerWebExchangeexchange,GatewayFilterChainchain){ //获取Request、Response对象 ServerHttpRequestrequest=exchange.getRequest(); ServerHttpResponseresponse=exchange.getResponse(); //获取请求的URI Stringpath=request.getURI().getPath(); //如果是登录、goods等开放的微服务[这里的goods部分开放],则直接放行,这里不做完整演示,完整演示需要设计一套权限系统 //未登录下只放行登录和搜索 if(path.startsWith("/api/user/login")||path.startsWith("/api/brand/search/")){ //放行 Mono filter=chain.filter(exchange); returnfilter; } //从头文件中获取的令牌信息 Stringtoken=request.getHeaders().getFirst(AUTHORIZE_TOKEN); //如果为true:说明令牌在头文件中,false:令牌不在头文件中,将令牌封装入头文件,再传递给其他微服务 booleanhasToken=true; //如果头文件中没有令牌信息,则从请求参数中获取 if(StringUtils.isEmpty(token)){ token=request.getQueryParams().getFirst(AUTHORIZE_TOKEN); hasToken=false; } //如果为空,则输出错误代码 if(StringUtils.isEmpty(token)){ //设置方法不允许被访问,405错误代码 response.setStatusCode(HttpStatus.METHOD_NOT_ALLOWED); returnresponse.setComplete(); } //如果不为空,则解析令牌数据 try{ Claimsclaims=JwtUtil.parseJWT(token); }catch(Exceptione){ e.printStackTrace(); //解析失败,响应401错误 response.setStatusCode(HttpStatus.UNAUTHORIZED); returnresponse.setComplete(); } //放行之前,将令牌封装到头文件中(这一步是为了方便AUTH2校验令牌) request.mutate().header(AUTHORIZE_TOKEN,token); //放行 returnchain.filter(exchange); } /** *过滤器执行顺序 * *@return */ @Override publicintgetOrder(){ //首位 return0; } }
3.2网关微服务application.yml
spring: cloud: gateway: globalcors: corsConfigurations: '[/**]':#匹配所有请求 allowedOrigins:"*"#跨域处理允许所有的域 allowedMethods:#支持的请求类型 -GET -POST -PUT -DELETE routes: #对接商品goods微服务路由相关配置 -id:changgou_goods_route uri:lb://changgou-goods predicates: -Path=/api/brand/**,/api/category/** filters: -StripPrefix=1 -name:RequestRateLimiter#请求数限流名字不能随便写,使用默认的facatory args: #用于限流的键的解析器的Bean对象的名字。它使用SpEL表达式根据#{@beanName}从Spring容器中获取Bean对象。 key-resolver:"#{@ipKeyResolver}" #令牌桶每秒填充平均速率 redis-rate-limiter.replenishRate:1 #令牌桶总容量 redis-rate-limiter.burstCapacity:1 #上面配置,表示1秒内,允许1个请求通过,令牌桶的填充速率也是1秒钟添加1个令牌。 #对接用户user微服务路由相关配置 -id:changgou_user_route uri:lb://changgou-user predicates: -Path=/api/user/**,/api/address/**,/api/areas/**,/api/cities/**,/api/provinces/** filters: #user微服务真实请求中是没有/api的,所以这里StripPrefix=1 -StripPrefix=1 #微服务名称 application: name:changgou-gateway-web #Redis配置 redis: #Redis数据库索引(默认为0) database:0 #Redis服务器地址 host:8.131.66.136 #Redis服务器连接端口 port:6379 #Redis服务器连接密码(默认为空) password:csp19990129 server: port:8001 eureka: client: service-url: defaultZone:http://127.0.0.1:7001/eureka instance: prefer-ip-address:true management: endpoint: gateway: enabled:true web: exposure: include:true
3.3网关微服务主启动类
/** *@Auther:csp1999 *@Date:2021/01/24/15:16 *@Description:用户/前台微服务网关启动类 */ @SpringBootApplication @EnableEurekaClient publicclassGatewayWebApplication{ publicstaticvoidmain(String[]args){ SpringApplication.run(GatewayWebApplication.class,args); } /** *IP限流:由用户请求的IP创建创建用户唯一标识,进而根据IP进行限流操作 * *@return */ @Bean(name="ipKeyResolver") publicKeyResolveruserKeyResolver(){ returnnewKeyResolver(){ @Override publicMonoresolve(ServerWebExchangeexchange){ //获取远程客户端IP StringhostName=exchange.getRequest().getRemoteAddress().getAddress().getHostAddress(); System.out.println("hostName:"+hostName); returnMono.just(hostName); } }; } }
3.4用户微服务编写登录代码
/** *@Author:csp1999 *@Description:User的Controller *@Date2021/1/140:18 */ @RestController @RequestMapping("/user") @CrossOrigin publicclassUserController{ @Autowired privateUserServiceuserService; /*** *修改User数据 *@paramuser *@paramid *@return */ @PutMapping(value="/{id}") publicResultupdate(@RequestBodyUseruser,@PathVariableStringid){ ... } /*** *新增User数据 *@paramuser *@return */ @PostMapping publicResultadd(@RequestBodyUseruser){ ... } /*** *根据ID查询User数据 *@paramid *@return */ @GetMapping("/{id}") publicResultfindById(@PathVariableStringid){ ... } /*** *查询User全部数据 *@return */ @GetMapping publicResult >findAll(){ ... } /*** *用户登录 *@paramusername *@parampassword *@paramresponse *@paramrequest *@return */ @RequestMapping("/login") publicResult
login(Stringusername,Stringpassword,HttpServletResponseresponse,HttpServletRequestrequest){ //1.从数据库中查询用户名对应的用户的对象 Useruser=userService.findById(username); if(user==null){ //2.判断用户是否为空为空返回数据 returnnewResult (false,StatusCode.LOGINERROR,"用户名或密码错误..."); } //3.如果不为空判断密码是否正确若正确则登录成功 if(BCrypt.checkpw(password,user.getPassword())){ //登录成功,讲用户信息存入map Map info=newHashMap (); info.put("role","USER"); info.put("success","SUCCESS"); info.put("username",username); //3.1生成令牌 Stringjwt=JwtUtil.createJWT(UUID.randomUUID().toString(),JSON.toJSONString(info),null); //3.2设置jwt存入cookie中 Cookiecookie=newCookie("Authorization",jwt); response.addCookie(cookie); //3.3设置jwt存入头文件中 response.setHeader("Authorization",jwt); returnnewResult (true,StatusCode.OK,"登录成功",jwt); }else{ //登录失败 returnnewResult (false,StatusCode.LOGINERROR,"用户名或密码错误"); } } }
到此这篇关于SpringCloudGateway使用JWT工具类做用户登录校验的示例代码的文章就介绍到这了,更多相关SpringCloudGateway用户登录校验内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!