gateway和jwt网关认证实现过程解析
这篇文章主要介绍了gateway和jwt网关认证实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
思路:全局过滤器对所有的请求拦截(生成token有效期30分钟,放入redis设置有效期3天。3天之类可以通过刷新接口自动刷新,超过3天需要重新登录。)
前端在调用接口之前先判断token是否过期(3o分钟),过期则先调刷新接口,换取新token,
1引入相关jar
org.springframework.cloud spring-cloud-starter-gateway io.jsonwebtoken jjwt 0.9.0
2编写Jwt工具类(生成token+解析token)
packagespring.cloud.gateway.common; importjava.text.DateFormat; importjava.text.SimpleDateFormat; importjava.util.Calendar; importjava.util.Date; importjava.util.HashMap; importjava.util.Map; importio.jsonwebtoken.ExpiredJwtException; importorg.springframework.util.StringUtils; importio.jsonwebtoken.Jwts; importio.jsonwebtoken.SignatureAlgorithm; publicclassJwtUtil{ publicstaticfinalStringSECRET="qazwsx123444$#%#()*&&asdaswwi1235?;!@#kmmmpomin***xx**&"; publicstaticfinalStringTOKEN_PREFIX="Bearer"; publicstaticfinalStringLOGIN_URL="/token/userId/pwd"; publicstaticfinalStringLOGOUT_URL="/token/userId"; publicstaticfinalStringHEADER_AUTH="authorization"; publicstaticfinalStringHEADER_USERID="userid"; //token超时时间 publicstaticfinalintTOKEN_EXPIRATION_MINUTE=30; //token的redis超时时间 publicstaticfinalintTOKEN_REDIS_EXPIRATION_DAY=7; publicstaticStringgenerateToken(StringuserId){ Calendarcalendar=Calendar.getInstance(); calendar.add(Calendar.MINUTE,TOKEN_EXPIRATION_MINUTE);//得到前一天 Datedate=calendar.getTime(); DateFormatdf=newSimpleDateFormat("yyyy-MM-ddHH:mm:ss"); df.format(date); //todo优化token的生层规则 HashMapmap=newHashMap<>(); map.put(HEADER_USERID,userId); Stringjwt=Jwts.builder() .setSubject(HEADER_USERID).setClaims(map) .setExpiration(date) .signWith(SignatureAlgorithm.HS512,SECRET) .compact(); returnTOKEN_PREFIX+""+jwt; } publicstaticMap validateToken(Stringtoken){ HashMap tokenMap=newHashMap (); if(StringUtils.isEmpty(token)){ returntokenMap; } try{ Map tokenBody=Jwts.parser() .setSigningKey(SECRET) .parseClaimsJws(token.replace(TOKEN_PREFIX,"")) .getBody(); StringuserId=String.valueOf(tokenBody.get(HEADER_USERID)); tokenMap.put(HEADER_USERID,userId); }catch(ExpiredJwtExceptione){ e.printStackTrace(); } returntokenMap; } /** *移到jwtUtil中去 * *@paramtoken *@return */ publicstaticMap validateTokenAndUser(Stringtoken,StringuserIdIn){ Map tokenResultMap=newHashMap<>(); if(StringUtils.isEmpty(token)||StringUtils.isEmpty(userIdIn)){ returntokenResultMap; } tokenResultMap=validateToken(token); if(StringUtils.isEmpty(token)||StringUtils.isEmpty(userIdIn)){ returntokenResultMap; } //判断传入的userid和token是否匹配 StringuserIdOri=tokenResultMap.get(HEADER_USERID); if(!userIdIn.equals(userIdOri)){ returnnewHashMap (); } returntokenResultMap; } }
3编写过滤器类
packagespring.cloud.gateway.filter; importjava.net.URI; importjava.util.Map; importorg.apache.commons.lang.StringUtils; importorg.springframework.cloud.gateway.filter.GatewayFilterChain; importorg.springframework.cloud.gateway.filter.GlobalFilter; importorg.springframework.cloud.gateway.route.Route; importorg.springframework.cloud.gateway.support.ServerWebExchangeUtils; importorg.springframework.http.HttpHeaders; importorg.springframework.http.HttpMethod; importorg.springframework.http.server.PathContainer; importorg.springframework.http.server.reactive.ServerHttpRequest; importorg.springframework.stereotype.Component; importorg.springframework.web.server.ServerWebExchange; importreactor.core.publisher.Mono; importspring.cloud.gateway.common.JwtUtil; importspring.cloud.gateway.exception.PermissionException; /** *参数参考https://blog.csdn.net/tianyaleixiaowu/article/details/83375246 *response参考https://bbs.csdn.net/topics/392412604?list=11074255 */ @Component publicclassAuthFilterimplementsGlobalFilter{ @Override publicMonofilter(ServerWebExchangeexchange,GatewayFilterChainchain){ ServerHttpRequestrequest=exchange.getRequest(); HttpHeadersheader=request.getHeaders(); HttpMethodmethod=request.getMethod(); Stringtoken=header.getFirst(JwtUtil.HEADER_AUTH); StringuserId=header.getFirst(JwtUtil.HEADER_USERID); PathContainerpathContainer=request.getPath().pathWithinApplication(); Stringpath=pathContainer.value(); //2-处理登录请求 if(StringUtils.isBlank(token)){ //是登录接口则放行,否则返回异常 if(path.contains(JwtUtil.LOGIN_URL)&&HttpMethod.POST.equals(method)){ thrownewPermissionException("pleaselogin"); } returnchain.filter(exchange); } //3-处理刷新token请求 if(path.indexOf("refresh")>=0){ //放行去掉刷新接口(在刷新前校验userId和token是否匹配) returnchain.filter(exchange); } //4-处理刷新token请求 if(path.contains(JwtUtil.LOGOUT_URL)&&HttpMethod.DELETE.equals(method)){ //放行去掉登出接口(在刷新前校验userId和token是否匹配) returnchain.filter(exchange); } //5-携带token请求其他业务接口 Map validateResultMap=JwtUtil.validateTokenAndUser(token,userId); if(validateResultMap==null||validateResultMap.isEmpty()){ thrownewPermissionException("token已经失效"); } //TODO将用户信息存放在请求header中传递给下游业务 RoutegatewayUrl=exchange.getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR); URIuri=gatewayUrl.getUri(); //表示下游请求对应的服务名如SPRING-CLOUD-SERVICESPRING-CLOUD-GATEWAY StringserviceName=uri.getHost(); ServerHttpRequest.Buildermutate=request.mutate(); mutate.header("x-user-id",validateResultMap.get("userid")); mutate.header("x-user-name",validateResultMap.get("user")); mutate.header("x-user-serviceName",serviceName); ServerHttpRequestbuildReuqest=mutate.build(); //todo如果响应中需要放数据,也可以放在response的header中 //ServerHttpResponseresponse=exchange.getResponse(); //response.getHeaders().add("new_token","token_value"); returnchain.filter(exchange.mutate().request(buildReuqest).build()); } }
4编写相关接口API
packagespring.cloud.gateway.controller; importorg.springframework.web.bind.annotation.*; importspring.cloud.gateway.common.JwtUtil; importjava.util.Map; @RestController @RequestMapping("/token") publicclassTokenController{ /** *登录接口 *@paramuser(userID+pwd) *@return */ @PostMapping("/userId/pwd") publicStringgetToken(@RequestBodyMapuser){ //用户名密码需要加密处理 Stringresult=""; if(user==null||user.isEmpty()){ returnresult; } StringuserId=user.get("userId"); Stringpwd=user.get("pwd"); if(!doLogin(userId,pwd)){ returnresult; } Stringtoken=JwtUtil.generateToken(userId); //todo将token放入redis中,设置超时时间为2*t returntoken; } privateBooleandoLogin(StringuserId,Stringpwd){ //后续对接user表验证 if("admin".equals(userId)&&"123".equals(pwd)){ returntrue; } if("spring".equals(userId)&&"123".equals(pwd)){ returntrue; } if("gateway".equals(userId)&&"123".equals(pwd)){ returntrue; } returnfalse; } /** *登出接口 */ /** *刷新token的接口 *在刷新前校验userId和token是否匹配 */ }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。