热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SpringCloudGateway使用JWT工具类做用户登录校验

1.JWT测试***Auther:csp1999*Date:2021012419:29*Description:JWT测试*publicclassJwtTest{***创建Jw

1. JWT测试

/*** @Auther: csp1999* @Date: 2021/01/24/19:29* @Description: JWT测试*/
public class JwtTest {/*** 创建Jwt令牌&#xff1a;** JWT &#61; 头部Header &#43; 载荷playload &#43; 签名signature*/&#64;Testpublic void testCreateJwt() {// 构建jwt令牌// 1.头部Header: 描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等JwtBuilder builder &#61; Jwts.builder().setId("8989") // 设置令牌唯一编号.setIssuer("csp1999") // 设置令牌颁发者.setSubject("JWT加密测试") // 设置令牌主题 可以是JSON数据.setIssuedAt(new Date()) // 设置令牌签发日期.setExpiration(new Date(System.currentTimeMillis() &#43; 1000 * 60 * 3));// 设置令牌过期时间 3分钟// 2.自定义载荷playload: 存放有效信息的地方Map<String,Object> userInfo &#61; new HashMap<>();userInfo.put("username","csp");userInfo.put("password","123456");userInfo.put("school","河南科技大学");userInfo.put("age","22");// 将载荷添加到JWT令牌中builder.addClaims(userInfo);// 3.为令牌设置 签名signaturebuilder.signWith(SignatureAlgorithm.HS256, "haust");// 设置令牌的签名 使用HS256算法&#xff0c;并设置SecretKey密钥(字符串)// 构建 并返回一个字符串String jwtStr &#61; builder.compact();System.out.println(jwtStr);}/*** 解析Jwt令牌数据*/&#64;Testpublic void testParseJwt() {// jwt字符串String jwtStr &#61; "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4OTg5IiwiaXNzIjoiY3NwMTk5OSIsInN1YiI6IkpXVOWKoOWvhua1i-ivlSIsImlhdCI6MTYxMTQ4ODc1MSwiZXhwIjoxNjExNDg4OTMxLCJwYXNzd29yZCI6IjEyMzQ1NiIsInNjaG9vbCI6Iuays-WNl-enkeaKgOWkp-WtpiIsImFnZSI6IjIyIiwidXNlcm5hbWUiOiJjc3AifQ.uH28G9MSHfzaKBAOyr8AdksYLVvy8O5P8g7TORZIUFY";// 解析jwt字符串Claims claims &#61; Jwts.parser().setSigningKey("haust"). // 密钥&#xff08;盐&#xff09;parseClaimsJws(jwtStr). // 要解析的令牌对象getBody(); // 获取解析后的结果// {jti&#61;8989, iss&#61;csp1999, sub&#61;JWT加密测试, iat&#61;1611488751, exp&#61;1611488931, password&#61;123456, school&#61;河南科技大学, age&#61;22, username&#61;csp}System.out.println(claims);}
}

2. JWT工具类

/*** &#64;Auther: csp1999* &#64;Date: 2021/01/24/19:29* &#64;Description: JWT工具类*/
public class JwtUtil {// 有效期为public static final Long JWT_TTL &#61; 3600000L;// 60 * 60 * 1000 一个小时// Jwt令牌信息public static final String JWT_KEY &#61; "itcast";/*** 生成令牌* &#64;param id* &#64;param subject* &#64;param ttlMillis* &#64;return*/public static String createJWT(String id, String subject, Long ttlMillis) {// 指定算法SignatureAlgorithm signatureAlgorithm &#61; SignatureAlgorithm.HS256;// 当前系统时间long nowMillis &#61; System.currentTimeMillis();// 令牌签发时间Date now &#61; new Date(nowMillis);// 如果令牌有效期为null&#xff0c;则默认设置有效期1小时if (ttlMillis &#61;&#61; null) {ttlMillis &#61; JwtUtil.JWT_TTL;}// 令牌过期时间设置long expMillis &#61; nowMillis &#43; ttlMillis;Date expDate &#61; new Date(expMillis);// 生成秘钥SecretKey secretKey &#61; generalKey();// 封装Jwt令牌信息JwtBuilder builder &#61; Jwts.builder().setId(id) //唯一的ID.setSubject(subject) // 主题 可以是JSON数据.setIssuer("admin") // 签发者.setIssuedAt(now) // 签发时间.signWith(signatureAlgorithm, secretKey) // 签名算法以及密匙.setExpiration(expDate); // 设置过期时间return builder.compact();}/*** 生成加密 secretKey** &#64;return*/public static SecretKey generalKey() {byte[] encodedKey &#61; Base64.getEncoder().encode(JwtUtil.JWT_KEY.getBytes());SecretKey key &#61; new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");return key;}/*** 解析令牌数据** &#64;param jwt* &#64;return* &#64;throws Exception*/public static Claims parseJWT(String jwt) throws Exception {SecretKey secretKey &#61; generalKey();return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwt).getBody();}public static void main(String[] args) {String jwt &#61; JwtUtil.createJWT("weiyibiaoshi", "aaaaaa", null);System.out.println(jwt);try {Claims claims &#61; JwtUtil.parseJWT(jwt);System.out.println(claims);} catch (Exception e) {e.printStackTrace();}}
}

3. 用户登录校验


3.1 网关过滤器

/*** &#64;Auther: csp1999* &#64;Date: 2021/01/24/20:17* &#64;Description: 授权过滤器*/
&#64;Component
public class AuthorizeFilter implements GlobalFilter, Ordered {// 令牌头名字private static final String AUTHORIZE_TOKEN &#61; "Authorization";/*** 全局过滤器** &#64;param exchange* &#64;param chain* &#64;return*/&#64;Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 获取Request、Response对象ServerHttpRequest request &#61; exchange.getRequest();ServerHttpResponse response &#61; exchange.getResponse();// 获取请求的URIString path &#61; request.getURI().getPath();// 如果是登录、goods等开放的微服务[这里的goods部分开放],则直接放行,这里不做完整演示&#xff0c;完整演示需要设计一套权限系统// 未登录下只放行登录和搜索if (path.startsWith("/api/user/login") || path.startsWith("/api/brand/search/")) {// 放行Mono<Void> filter &#61; chain.filter(exchange);return filter;}// 从头文件中获取的令牌信息String token &#61; request.getHeaders().getFirst(AUTHORIZE_TOKEN);// 如果为true&#xff1a;说明令牌在头文件中&#xff0c; false&#xff1a;令牌不在头文件中&#xff0c;将令牌封装入头文件&#xff0c;再传递给其他微服务boolean hasToken &#61; true;// 如果头文件中没有令牌信息&#xff0c;则从请求参数中获取if (StringUtils.isEmpty(token)) {token &#61; request.getQueryParams().getFirst(AUTHORIZE_TOKEN);hasToken &#61; false;}// 如果为空&#xff0c;则输出错误代码if (StringUtils.isEmpty(token)) {// 设置方法不允许被访问&#xff0c;405错误代码response.setStatusCode(HttpStatus.METHOD_NOT_ALLOWED);return response.setComplete();}// 如果不为空&#xff0c;则解析令牌数据try {Claims claims &#61; JwtUtil.parseJWT(token);} catch (Exception e) {e.printStackTrace();// 解析失败&#xff0c;响应401错误response.setStatusCode(HttpStatus.UNAUTHORIZED);return response.setComplete();}// 放行之前&#xff0c;将令牌封装到头文件中(这一步是为了方便AUTH2校验令牌)request.mutate().header(AUTHORIZE_TOKEN,token);// 放行return chain.filter(exchange);}/*** 过滤器执行顺序** &#64;return*/&#64;Overridepublic int getOrder() {// 首位return 0;}
}

3.2 网关微服务application.yml

spring:cloud:gateway:globalcors:corsConfigurations:&#39;[/**]&#39;: # 匹配所有请求allowedOrigins: "*" # 跨域处理 允许所有的域allowedMethods: #支持的请求类型- GET- POST- PUT- DELETEroutes:# 对接商品goods微服务路由相关配置- id: changgou_goods_routeuri: lb://changgou-goodspredicates:- Path&#61;/api/brand/**,/api/category/**filters:- StripPrefix&#61;1- name: RequestRateLimiter # 请求数限流 名字不能随便写 &#xff0c;使用默认的facatoryargs:# 用于限流的键的解析器的 Bean 对象的名字。它使用 SpEL 表达式根据#{&#64;beanName}从 Spring 容器中获取 Bean 对象。key-resolver: "#{&#64;ipKeyResolver}"# 令牌桶每秒填充平均速率redis-rate-limiter.replenishRate: 1# 令牌桶总容量redis-rate-limiter.burstCapacity: 1# 上面配置&#xff0c;表示1秒内&#xff0c;允许 1个请求通过&#xff0c;令牌桶的填充速率也是1秒钟添加1个令牌。# 对接用户user微服务路由相关配置- id: changgou_user_routeuri: lb://changgou-userpredicates:- Path&#61;/api/user/**,/api/address/**,/api/areas/**,/api/cities/**,/api/provinces/**filters:# user微服务真实请求中是没有/api的&#xff0c;所以这里StripPrefix&#61;1- StripPrefix&#61;1# 微服务名称application:name: changgou-gateway-web# Redis配置redis:# Redis数据库索引&#xff08;默认为0&#xff09;database: 0# Redis服务器地址host: 8.131.66.136# Redis服务器连接端口port: 6379# Redis服务器连接密码&#xff08;默认为空&#xff09;password: csp19990129server:port: 8001
eureka:client:service-url:defaultZone: http://127.0.0.1:7001/eurekainstance:prefer-ip-address: true
management:endpoint:gateway:enabled: trueweb:exposure:include: true

3.3 网关微服务主启动类

/*** &#64;Auther: csp1999* &#64;Date: 2021/01/24/15:16* &#64;Description: 用户/前台微服务网关启动类*/
&#64;SpringBootApplication
&#64;EnableEurekaClient
public class GatewayWebApplication {public static void main(String[] args) {SpringApplication.run(GatewayWebApplication.class, args);}/*** IP限流&#xff1a;由用户请求的IP创建创建用户唯一标识&#xff0c;进而根据IP进行限流操作** &#64;return*/&#64;Bean(name &#61; "ipKeyResolver")public KeyResolver userKeyResolver() {return new KeyResolver() {&#64;Overridepublic Mono<String> resolve(ServerWebExchange exchange) {// 获取远程客户端IPString hostName &#61; exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();System.out.println("hostName:" &#43; hostName);return Mono.just(hostName);}};}
}

3.4 用户微服务编写登录代码

/*** &#64;Author: csp1999* &#64;Description: User 的Controller* &#64;Date 2021/1/14 0:18*/
&#64;RestController
&#64;RequestMapping("/user")
&#64;CrossOrigin
public class UserController {&#64;Autowiredprivate UserService userService;/**** 修改User数据* &#64;param user* &#64;param id* &#64;return*/&#64;PutMapping(value &#61; "/{id}")public Result update(&#64;RequestBody User user, &#64;PathVariable String id) {...}/**** 新增User数据* &#64;param user* &#64;return*/&#64;PostMappingpublic Result add(&#64;RequestBody User user) {...}/**** 根据ID查询User数据* &#64;param id* &#64;return*/&#64;GetMapping("/{id}")public Result<User> findById(&#64;PathVariable String id) {...}/**** 查询User全部数据* &#64;return*/&#64;GetMappingpublic Result<List<User>> findAll() {...}/**** 用户登录* &#64;param username* &#64;param password* &#64;param response* &#64;param request* &#64;return*/&#64;RequestMapping("/login")public Result<User> login(String username, String password, HttpServletResponse response, HttpServletRequest request) {// 1.从数据库中查询用户名对应的用户的对象User user &#61; userService.findById(username);if (user &#61;&#61; null) {// 2.判断用户是否为空 为空返回数据return new Result<User>(false, StatusCode.LOGINERROR, "用户名或密码错误...");}// 3.如果不为空 判断密码是否正确 若正确 则登录成功if (BCrypt.checkpw(password, user.getPassword())) {// 登录成功,讲用户信息存入mapMap<String, Object> info &#61; new HashMap<String, Object>();info.put("role", "USER");info.put("success", "SUCCESS");info.put("username", username);// 3.1生成令牌String jwt &#61; JwtUtil.createJWT(UUID.randomUUID().toString(), JSON.toJSONString(info), null);// 3.2设置jwt存入 COOKIE 中COOKIE COOKIE &#61; new COOKIE("Authorization", jwt);response.addCOOKIE(COOKIE);// 3.3设置jwt存入头文件中response.setHeader("Authorization", jwt);return new Result<User>(true, StatusCode.OK, "登录成功", jwt);} else {// 登录失败return new Result<User>(false, StatusCode.LOGINERROR, "用户名或密码错误");}}
}


推荐阅读
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 本文介绍了使用Spark实现低配版高斯朴素贝叶斯模型的原因和原理。随着数据量的增大,单机上运行高斯朴素贝叶斯模型会变得很慢,因此考虑使用Spark来加速运行。然而,Spark的MLlib并没有实现高斯朴素贝叶斯模型,因此需要自己动手实现。文章还介绍了朴素贝叶斯的原理和公式,并对具有多个特征和类别的模型进行了讨论。最后,作者总结了实现低配版高斯朴素贝叶斯模型的步骤。 ... [详细]
  • 超级简单加解密工具的方案和功能
    本文介绍了一个超级简单的加解密工具的方案和功能。该工具可以读取文件头,并根据特定长度进行加密,加密后将加密部分写入源文件。同时,该工具也支持解密操作。加密和解密过程是可逆的。本文还提到了一些相关的功能和使用方法,并给出了Python代码示例。 ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
  • WebSocket与Socket.io的理解
    WebSocketprotocol是HTML5一种新的协议。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送 ... [详细]
  • 怎么在PHP项目中实现一个HTTP断点续传功能发布时间:2021-01-1916:26:06来源:亿速云阅读:96作者:Le ... [详细]
  • 导出功能protectedvoidbtnExport(objectsender,EventArgse){用来打开下载窗口stringfileName中 ... [详细]
  • ScrollView嵌套Collectionview无痕衔接四向滚动,支持自定义TitleView
    本文介绍了如何实现ScrollView嵌套Collectionview无痕衔接四向滚动,并支持自定义TitleView。通过使用MainScrollView作为最底层,headView作为上部分,TitleView作为中间部分,Collectionview作为下面部分,实现了滚动效果。同时还介绍了使用runtime拦截_notifyDidScroll方法来实现滚动代理的方法。具体实现代码可以在github地址中找到。 ... [详细]
author-avatar
晏圣玲
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有