十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
使用gateway和jwt怎么实现网关认证?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
创新互联是一家集网站建设,雷山企业网站建设,雷山品牌网站建设,网站定制,雷山网站建设报价,网络营销,网络优化,雷山网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。
1引入相关jar
org.springframework.cloud spring-cloud-starter-gateway io.jsonwebtoken jjwt 0.9.0
2编写Jwt工具类(生成token + 解析token)
package spring.cloud.gateway.common; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.Map; import io.jsonwebtoken.ExpiredJwtException; import org.springframework.util.StringUtils; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; public class JwtUtil { public static final String SECRET = "qazwsx123444$#%#()*&& asdaswwi1235 ?;!@#kmmmpom in***xx**&"; public static final String TOKEN_PREFIX = "Bearer"; public static final String LOGIN_URL = "/token/userId/pwd"; public static final String LOGOUT_URL = "/token/userId"; public static final String HEADER_AUTH = "authorization"; public static final String HEADER_USERID = "userid"; //token超时时间 public static final int TOKEN_EXPIRATION_MINUTE = 30; //token的redis超时时间 public static final int TOKEN_REDIS_EXPIRATION_DAY = 7; public static String generateToken(String userId) { Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.MINUTE, TOKEN_EXPIRATION_MINUTE); //得到前一天 Date date = calendar.getTime(); DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); df.format(date); //todo 优化token的生层规则 HashMapmap = new HashMap<>(); map.put(HEADER_USERID, userId); String jwt = Jwts.builder() .setSubject(HEADER_USERID).setClaims(map) .setExpiration(date) .signWith(SignatureAlgorithm.HS512, SECRET) .compact(); return TOKEN_PREFIX + " " + jwt; } public static Map validateToken(String token) { HashMap tokenMap = new HashMap (); if (StringUtils.isEmpty(token)) { return tokenMap; } try { Map tokenBody = Jwts.parser() .setSigningKey(SECRET) .parseClaimsJws(token.replace(TOKEN_PREFIX, "")) .getBody(); String userId = String.valueOf(tokenBody.get(HEADER_USERID)); tokenMap.put(HEADER_USERID, userId); }catch (ExpiredJwtException e){ e.printStackTrace(); } return tokenMap; } /** * 移到jwtUtil中去 * * @param token * @return */ public static Map validateTokenAndUser(String token, String userIdIn) { Map tokenResultMap = new HashMap<>(); if (StringUtils.isEmpty(token) || StringUtils.isEmpty(userIdIn)) { return tokenResultMap; } tokenResultMap = validateToken(token); if (StringUtils.isEmpty(token) || StringUtils.isEmpty(userIdIn)) { return tokenResultMap; } //判断传入的userid和token是否匹配 String userIdOri = tokenResultMap.get(HEADER_USERID); if (!userIdIn.equals(userIdOri)) { return new HashMap (); } return tokenResultMap; } }
3编写过滤器类
package spring.cloud.gateway.filter; import java.net.URI; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.cloud.gateway.route.Route; import org.springframework.cloud.gateway.support.ServerWebExchangeUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.server.PathContainer; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import spring.cloud.gateway.common.JwtUtil; import spring.cloud.gateway.exception.PermissionException; /** * 参数参考 https://blog.csdn.net/tianyaleixiaowu/article/details/83375246 * response参考 https://bbs.csdn.net/topics/392412604?list=11074255 */ @Component public class AuthFilter implements GlobalFilter { @Override public Monofilter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); HttpHeaders header = request.getHeaders(); HttpMethod method = request.getMethod(); String token = header.getFirst(JwtUtil.HEADER_AUTH); String userId = header.getFirst(JwtUtil.HEADER_USERID); PathContainer pathContainer = request.getPath().pathWithinApplication(); String path = pathContainer.value(); //2- 处理登录请求 if (StringUtils.isBlank(token)) { //是登录接口则放行,否则返回异常 if (path.contains(JwtUtil.LOGIN_URL) && HttpMethod.POST.equals(method)) { throw new PermissionException("please login"); } return chain.filter(exchange); } //3- 处理刷新token请求 if (path.indexOf("refresh") >= 0) { //放行去掉刷新接口(在刷新前校验userId和token是否匹配) return chain.filter(exchange); } //4- 处理刷新token请求 if (path.contains(JwtUtil.LOGOUT_URL) && HttpMethod.DELETE.equals(method)) { //放行去掉登出接口(在刷新前校验userId和token是否匹配) return chain.filter(exchange); } //5- 携带token请求其他业务接口 Map validateResultMap = JwtUtil.validateTokenAndUser(token, userId); if (validateResultMap == null || validateResultMap.isEmpty()) { throw new PermissionException("token 已经失效"); } // TODO 将用户信息存放在请求header中传递给下游业务 Route gatewayUrl = exchange.getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR); URI uri = gatewayUrl.getUri(); //表示下游请求对应的服务名如 SPRING-CLOUD-SERVICE SPRING-CLOUD-GATEWAY String serviceName = uri.getHost(); ServerHttpRequest.Builder mutate = request.mutate(); mutate.header("x-user-id", validateResultMap.get("userid")); mutate.header("x-user-name", validateResultMap.get("user")); mutate.header("x-user-serviceName", serviceName); ServerHttpRequest buildReuqest = mutate.build(); //todo 如果响应中需要放数据,也可以放在response的header中 //ServerHttpResponse response = exchange.getResponse(); //response.getHeaders().add("new_token","token_value"); return chain.filter(exchange.mutate().request(buildReuqest).build()); } }
4编写相关接口API
package spring.cloud.gateway.controller; import org.springframework.web.bind.annotation.*; import spring.cloud.gateway.common.JwtUtil; import java.util.Map; @RestController @RequestMapping("/token") public class TokenController { /** * 登录接口 * @param user(userID +pwd) * @return */ @PostMapping("/userId/pwd") public String getToken(@RequestBody Mapuser) { //用户名密码需要加密处理 String result = ""; if (user == null || user.isEmpty()) { return result; } String userId = user.get("userId"); String pwd = user.get("pwd"); if (!doLogin(userId,pwd)) { return result; } String token = JwtUtil.generateToken(userId); // todo 将token放入redis中,设置超时时间为 2 * t return token; } private Boolean doLogin(String userId,String pwd) { //后续对接user表验证 if ("admin".equals(userId) && "123".equals(pwd)) { return true; } if ("spring".equals(userId) && "123".equals(pwd)) { return true; } if ("gateway".equals(userId) && "123".equals(pwd)) { return true; } return false; } /** * 登出接口 */ /** * 刷新token的接口 * 在刷新前校验userId和token是否匹配 */ }
关于使用gateway和jwt怎么实现网关认证问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注创新互联行业资讯频道了解更多相关知识。