真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

如何使用JWT對(duì)SpringCloud進(jìn)行認(rèn)證和鑒權(quán)

這篇文章主要為大家展示了“如何使用JWT對(duì)SpringCloud進(jìn)行認(rèn)證和鑒權(quán)”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“如何使用JWT對(duì)SpringCloud進(jìn)行認(rèn)證和鑒權(quán)”這篇文章吧。

創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供武岡網(wǎng)站建設(shè)、武岡做網(wǎng)站、武岡網(wǎng)站設(shè)計(jì)、武岡網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)與制作、武岡企業(yè)網(wǎng)站模板建站服務(wù),十年武岡做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。

JWT(JSON WEB TOKEN)是基于RFC 7519標(biāo)準(zhǔn)定義的一種可以安全傳輸?shù)男∏珊妥园腏SON對(duì)象。由于數(shù)據(jù)是使用數(shù)字簽名的,所以是可信任的和安全的。JWT可以使用HMAC算法對(duì)secret進(jìn)行加密或者使用RSA的公鑰私鑰對(duì)來進(jìn)行簽名。

JWT通常由頭部(Header),負(fù)載(Payload),簽名(Signature)三個(gè)部分組成,中間以.號(hào)分隔,其格式為Header.Payload.Signature

Header:聲明令牌的類型和使用的算法

  • alg:簽名的算法

  • typ:token的類型,比如JWT

Payload:也稱為JWT Claims,包含用戶的一些信息

系統(tǒng)保留的聲明(Reserved claims):

  • iss (issuer):簽發(fā)人

  • exp (expiration time):過期時(shí)間

  • sub (subject):主題

  • aud (audience):受眾用戶

  • nbf (Not Before):在此之前不可用

  • iat (Issued At):簽發(fā)時(shí)間

  •  jti (JWT ID):JWT唯一標(biāo)識(shí),能用于防止JWT重復(fù)使用

公共的聲明(public):見 http://www.iana.org/assignments/jwt/jwt.xhtml

私有的聲明(private claims):根據(jù)業(yè)務(wù)需要自己定義的數(shù)據(jù)

Signature:簽名

簽名格式: HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

JWT的特點(diǎn):

  • JWT默認(rèn)是不加密的,不能把用戶敏感類信息放在Payload部分。

  • JWT 不僅可以用于認(rèn)證,也可以用于交換信息。

  • JWT的最大缺點(diǎn)是服務(wù)器不保存會(huì)話狀態(tài),所以在使用期間不可能取消令牌或更改令牌的權(quán)限。

  • JWT本身包含認(rèn)證信息,為了減少盜用,JWT的有效期不宜設(shè)置太長。

  • 為了減少盜用和竊取,JWT不建議使用HTTP協(xié)議來傳輸代碼,而是使用加密的HTTPS協(xié)議進(jìn)行傳輸。

  • 首次生成token比較慢,比較耗CPU,在高并發(fā)的情況下需要考慮CPU占用問題。

  • 生成的token比較長,可能需要考慮流量問題。

認(rèn)證原理:

  • 客戶端向服務(wù)器申請(qǐng)授權(quán),服務(wù)器認(rèn)證以后,生成一個(gè)token字符串并返回給客戶端,此后客戶端在請(qǐng)求

  • 受保護(hù)的資源時(shí)攜帶這個(gè)token,服務(wù)端進(jìn)行驗(yàn)證再從這個(gè)token中解析出用戶的身份信息。

JWT的使用方式:一種做法是放在HTTP請(qǐng)求的頭信息Authorization字段里面,格式如下:

Authorization:

 需要將服務(wù)器設(shè)置為接受來自所有域的請(qǐng)求,用Access-Control-Allow-Origin: *

  另一種做法是,跨域的時(shí)候,JWT就放在POST請(qǐng)求的數(shù)據(jù)體里面。

對(duì)JWT實(shí)現(xiàn)token續(xù)簽的做法:

1、額外生成一個(gè)refreshToken用于獲取新token,refreshToken需存儲(chǔ)于服務(wù)端,其過期時(shí)間比JWT的過期時(shí)間要稍長。

2、用戶攜帶refreshToken參數(shù)請(qǐng)求token刷新接口,服務(wù)端在判斷refreshToken未過期后,取出關(guān)聯(lián)的用戶信息和當(dāng)前token。

3、使用當(dāng)前用戶信息重新生成token,并將舊的token置于黑名單中,返回新的token。

創(chuàng)建用于登錄認(rèn)證的工程auth-service:

1、 創(chuàng)建pom.xml文件

 
 4.0.0 
 com.seasy.springcloud 
 auth-service 
 1.0.0 
 jar 
  
  
  org.springframework.boot 
  spring-boot-starter-parent 
  2.0.8.RELEASE 
   
  
 
  
  1.8 
  UTF-8 
  UTF-8 
  
  
  
    
    org.springframework.boot  
    spring-boot-starter-web 
   
   
    org.springframework.boot 
    spring-boot-starter-actuator 
   
   
   
   
    org.springframework.cloud 
    spring-cloud-starter-netflix-eureka-client 
   
   
   
   
    org.springframework.boot 
    spring-boot-starter-data-redis 
   
   
    org.apache.commons 
    commons-pool2 
   
   
   
   
    com.auth0 
    java-jwt 
    3.7.0 
   
  
  
  
   
     
      org.springframework.cloud 
      spring-cloud-dependencies 
      Finchley.RELEASE 
      pom 
      import 
     
   
  

2、JWT工具類

public class JWTUtil { 
  public static final String SECRET_KEY = "123456"; //秘鑰 
  public static final long TOKEN_EXPIRE_TIME = 5 * 60 * 1000; //token過期時(shí)間 
  public static final long REFRESH_TOKEN_EXPIRE_TIME = 10 * 60 * 1000; //refreshToken過期時(shí)間 
  private static final String ISSUER = "issuer"; //簽發(fā)人 
 
  /** 
   * 生成簽名 
   */ 
  public static String generateToken(String username){ 
    Date now = new Date(); 
    Algorithm algorithm = Algorithm.HMAC256(SECRET_KEY); //算法 
     
    String token = JWT.create() 
      .withIssuer(ISSUER) //簽發(fā)人 
      .withIssuedAt(now) //簽發(fā)時(shí)間 
      .withExpiresAt(new Date(now.getTime() + TOKEN_EXPIRE_TIME)) //過期時(shí)間 
      .withClaim("username", username) //保存身份標(biāo)識(shí) 
      .sign(algorithm); 
    return token; 
  } 
   
  /** 
   * 驗(yàn)證token 
   */ 
  public static boolean verify(String token){ 
    try { 
      Algorithm algorithm = Algorithm.HMAC256(SECRET_KEY); //算法 
      JWTVerifier verifier = JWT.require(algorithm) 
          .withIssuer(ISSUER) 
          .build(); 
      verifier.verify(token); 
      return true; 
    } catch (Exception ex){ 
      ex.printStackTrace(); 
    } 
    return false; 
  } 
   
  /** 
   * 從token獲取username 
   */ 
  public static String getUsername(String token){ 
    try{ 
      return JWT.decode(token).getClaim("username").asString(); 
    }catch(Exception ex){ 
      ex.printStackTrace(); 
    } 
    return ""; 
  } 
}

3、LoginController類

@RestController 
public class LoginController { 
  @Autowired 
  StringRedisTemplate redisTemplate; 
   
  /** 
   * 登錄認(rèn)證 
   * @param username 用戶名 
   * @param password 密碼 
   */ 
  @GetMapping("/login") 
  public AuthResult login(@RequestParam String username, @RequestParam String password) { 
    if("admin".equals(username) && "admin".equals(password)){ 
      //生成token 
      String token = JWTUtil.generateToken(username); 
       
      //生成refreshToken 
      String refreshToken = StringUtil.getUUIDString(); 
       
      //數(shù)據(jù)放入redis 
      redisTemplate.opsForHash().put(refreshToken, "token", token); 
      redisTemplate.opsForHash().put(refreshToken, "username", username); 
       
      //設(shè)置token的過期時(shí)間 
      redisTemplate.expire(refreshToken, JWTUtil.REFRESH_TOKEN_EXPIRE_TIME, TimeUnit.MILLISECONDS); 
       
      return new AuthResult(0, "success", token, refreshToken); 
    }else{ 
      return new AuthResult(1001, "username or password error"); 
    } 
  } 
   
  /** 
   * 刷新token 
   */ 
  @GetMapping("/refreshToken") 
  public AuthResult refreshToken(@RequestParam String refreshToken) { 
    String username = (String)redisTemplate.opsForHash().get(refreshToken, "username"); 
    if(StringUtil.isEmpty(username)){ 
      return new AuthResult(1003, "refreshToken error"); 
    } 
 
    //生成新的token 
    String newToken = JWTUtil.generateToken(username); 
    redisTemplate.opsForHash().put(refreshToken, "token", newToken); 
    return new AuthResult(0, "success", newToken, refreshToken); 
  } 
 
  @GetMapping("/") 
  public String index() { 
    return "auth-service: " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); 
  } 
}

4、application配置信息

spring.application.name=auth-service 
server.port=4040 
 
eureka.instance.hostname=${spring.cloud.client.ip-address} 
eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port} 
eureka.instance.prefer-ip-address=true 
 
eureka.client.service-url.defaultZone=http://root:123456@${eureka.instance.hostname}:7001/eureka/ 
 
#redis 
spring.redis.database=0 
spring.redis.timeout=3000ms 
spring.redis.lettuce.pool.max-active=100 
spring.redis.lettuce.pool.max-wait=-1ms 
spring.redis.lettuce.pool.min-idle=0 
spring.redis.lettuce.pool.max-idle=8 
 
#standalone 
spring.redis.host=192.168.134.134 
spring.redis.port=7001 
 
#sentinel 
#spring.redis.sentinel.master=mymaster 
#spring.redis.sentinel.nodes=192.168.134.134:26379,192.168.134.134:26380

5、啟動(dòng)類

@SpringBootApplication 
@EnableEurekaClient 
public class Main{ 
  public static void main(String[] args){ 
    SpringApplication.run(Main.class, args); 
  } 
}

改造SpringCloud Gateway工程

1、在pom.xml文件添加依賴

 
 
  org.springframework.boot 
  spring-boot-starter-data-redis 
 
 
  org.apache.commons 
  commons-pool2 
 
 
 
 
  com.auth0 
  java-jwt 
  3.7.0 

2、創(chuàng)建全局過濾器JWTAuthFilter

@Component 
public class JWTAuthFilter implements GlobalFilter, Ordered{ 
  @Override 
  public int getOrder() { 
    return -100; 
  } 
   
  @Override 
  public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { 
    String url = exchange.getRequest().getURI().getPath(); 
     
    //忽略以下url請(qǐng)求 
    if(url.indexOf("/auth-service/") >= 0){ 
      return chain.filter(exchange); 
    } 
     
    //從請(qǐng)求頭中取得token 
    String token = exchange.getRequest().getHeaders().getFirst("Authorization"); 
    if(StringUtil.isEmpty(token)){ 
      ServerHttpResponse response = exchange.getResponse(); 
      response.setStatusCode(HttpStatus.OK); 
      response.getHeaders().add("Content-Type", "application/json;charset=UTF-8"); 
       
      Response res = new Response(401, "401 unauthorized"); 
      byte[] responseByte = JSONObject.fromObject(res).toString().getBytes(StandardCharsets.UTF_8); 
       
      DataBuffer buffer = response.bufferFactory().wrap(responseByte); 
      return response.writeWith(Flux.just(buffer)); 
    } 
     
    //請(qǐng)求中的token是否在redis中存在 
    boolean verifyResult = JWTUtil.verify(token); 
    if(!verifyResult){ 
      ServerHttpResponse response = exchange.getResponse(); 
      response.setStatusCode(HttpStatus.OK); 
      response.getHeaders().add("Content-Type", "application/json;charset=UTF-8"); 
 
      Response res = new Response(1004, "invalid token"); 
      byte[] responseByte = JSONObject.fromObject(res).toString().getBytes(StandardCharsets.UTF_8); 
       
      DataBuffer buffer = response.bufferFactory().wrap(responseByte); 
      return response.writeWith(Flux.just(buffer)); 
    } 
     
    return chain.filter(exchange); 
  } 
}

3、關(guān)鍵的application配置信息

spring: 
 application: 
  name: service-gateway 
 cloud: 
  gateway: 
   discovery: 
    locator: 
     enabled: true 
     lowerCaseServiceId: true 
   routes: 
    #認(rèn)證服務(wù)路由 
    - id: auth-service 
     predicates: 
      - Path=/auth-service/** 
     uri: lb://auth-service 
     filters: 
      - StripPrefix=1

以上是“如何使用JWT對(duì)SpringCloud進(jìn)行認(rèn)證和鑒權(quán)”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!


當(dāng)前標(biāo)題:如何使用JWT對(duì)SpringCloud進(jìn)行認(rèn)證和鑒權(quán)
本文來源:http://weahome.cn/article/isjiip.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部