微服务鉴权代码实现(Spring Cloud)
2019-08-16 本文已影响18人
月哥说了算
1557906391792.png
- 用户进入网关开始登陆,网关过滤器进行判断,如果是登录,则路由到后台管理微服务进行登录
- 用户登录成功,后台管理微服务签发JWT TOKEN信息返回给用户
- 用户再次进入网关开始访问,网关过滤器接收用户携带的TOKEN
- 网关过滤器解析TOKEN ,判断是否有权限,如果有,则放行,如果没有则返回未认证错误。
JWT签发工具类
package com.changgou.system.util;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;
/**
* JWT工具类
*/
public class JwtUtil {
//设置秘钥明文
public static final String JWT_KEY = "gzy";
/**
* 创建token
* @param id
* @param subject
* @param ttlMillis
* @return
*/
public static String createJWT(String id, String subject, Long ttlMillis) {
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
long expMillis = nowMillis + ttlMillis;
Date expDate = new Date(expMillis);
SecretKey secretKey = generalKey();
JwtBuilder builder = Jwts.builder()
.setId(id) //唯一的ID
.setSubject(subject) // 主题 可以是JSON数据
.setIssuer("admin") // 签发者
.setIssuedAt(now) // 签发时间
.signWith(signatureAlgorithm, secretKey) //使用HS256对称加密算法签名, 第二个参数为秘钥
.setExpiration(expDate);// 设置过期时间
return builder.compact();
}
/**
* 生成加密后的秘钥 secretKey
* @return
*/
public static SecretKey generalKey() {
byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);
SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
return key;
}
}
JWT校验工具类
package com.changgou.gateway.util;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
/**
* jwt校验工具类
*/
public class JwtUtil {
//设置秘钥明文
public static final String JWT_KEY = "gzy";
/**
* 生成加密后的秘钥 secretKey
*
* @return
*/
public static SecretKey generalKey() {
byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);
SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
return key;
}
/**
* 解析
*
* @param jwt
* @return
* @throws Exception
*/
public static Claims parseJWT(String jwt) throws Exception {
SecretKey secretKey = generalKey();
return Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(jwt)
.getBody();
}
}
本次鉴权功能有两个微服务实现,网关微服务,用户微服务。
用户微服务:
controller签发令牌:
/**
* 登录
* @param admin
* @return
*/
@PostMapping("/admin/login")
public Result login(@RequestBody Admin admin){
boolean login = adminService.login(admin);
if(login){
//创建token
String token = JwtUtil.createJWT( UUID.randomUUID().toString(), admin.getLoginName(), 60 * 60 * 1000L );
Map info=new HashMap( );
info.put( "username", admin.getLoginName());
info.put( "token",token );
return new Result(true,StatusCode.OK,"登录成功",info);
}else{
return new Result(false,StatusCode.LOGINERROR,"用户名或密码错误");
}
}
网关微服务校验令牌(全局拦截器实现)
网关微服务需要的依赖:
<!--鉴权-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
拦截器:
package com.changgou.filter;
import com.changgou.utils.JwtUtil;
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;
/**
* @author :gzy
* @date :Created in 2019/8/16
* @description :
* @version: 1.0
*/
@Component
public class SystemFilter implements GlobalFilter,Ordered {
private final String TOKRN="token";
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
String path = request.getURI().getPath();
System.out.println("拦截请求地址"+path);
//如果是登录请求不校验不拦截
if(!path.equals("/admin/login")){
String token = request.getHeaders().getFirst(TOKRN);
try {
JwtUtil.parseJWT(token);
return chain.filter(exchange);
} catch (Exception e) {
e.printStackTrace();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
//这里注意拦截顺序,一定要在去除前缀之后拦截。
return 2;
}
}