<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          微服務(wù)網(wǎng)關(guān):spring cloud gateway實(shí)現(xiàn)jwt統(tǒng)一認(rèn)證

          共 6282字,需瀏覽 13分鐘

           ·

          2020-10-20 13:43

          點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”

          優(yōu)質(zhì)文章,第一時(shí)間送達(dá)

          ? 作者?|??堅(jiān)持堅(jiān)持

          來源 |? urlify.cn/VjIZJ3

          66套java從入門到精通實(shí)戰(zhàn)課程分享

          當(dāng)你的項(xiàng)目中服務(wù)越來越多,每個(gè)服務(wù)都有自己的監(jiān)聽地址而又需要把這些服務(wù)提供給各式的客戶端或第三方使用,那么需要把每個(gè)服務(wù)地址都暴露出來嗎?如果某個(gè)服務(wù)有多個(gè)運(yùn)行實(shí)例,如果進(jìn)行負(fù)載均衡?用戶認(rèn)證和授權(quán)需要在每個(gè)服務(wù)上都做嗎,能否統(tǒng)一做?要解決這些問題,就需要用到Api網(wǎng)關(guān),Api網(wǎng)關(guān)提供Api請求轉(zhuǎn)發(fā)服務(wù)并可與Eureka結(jié)合實(shí)現(xiàn)路由轉(zhuǎn)發(fā)和負(fù)載均衡,同時(shí)利用AOP特性可以實(shí)現(xiàn)微服務(wù)用戶統(tǒng)一認(rèn)證和授權(quán)。目前比較流行的Api網(wǎng)關(guān)有Zuul、springcloud gateway以及支持dotnetcore的ocelot。本文使用的是springcloud。

          一,搭建springcloud gateway

          1,新建一個(gè)springboot項(xiàng)目,引入eureka-client和stater-gateway


          ????
          ????????org.springframework.cloud
          ????????spring-cloud-starter-gateway
          ????

          ????
          ????????org.springframework.cloud
          ????????spring-cloud-starter-netflix-eureka-client
          ????

          ????
          ????????org.springframework.boot
          ????????spring-boot-starter-test
          ????????test
          ????????
          ????????????
          ????????????????org.junit.vintage
          ????????????????junit-vintage-engine
          ????????????

          ????????

          ????


          2,項(xiàng)目配置文件:Application.yml

          server:
          ??port:?8020
          spring:
          ??application:
          ????name:?gateway-server
          ??cloud:
          ????gateway:
          ??????discovery:
          ????????locator:
          ??????????enabled:?true?//啟用網(wǎng)關(guān)服務(wù)發(fā)關(guān)
          ??????????lower-case-service-id:?true?//支持小寫字母的服務(wù)名稱(注冊到eureka的服務(wù))
          ek:
          ??username:?eureka
          ??password:?123456
          ??eureka-url:?127.0.0.1
          ??eureka-port:?8765
          eureka:
          ??client:
          ????service-url:
          ??????defaultZone:
          ????????http://${ek.username}:${ek.password}@${ek.eureka-url}:${ek.eureka-port}/eureka??//Eureka注冊地址
          ??instance:
          ????prefer-ip-address:?true??//啟用優(yōu)先IP地址注冊
          ????instance-id:?${spring.application.name}@${spring.cloud.client.ip-address}@${server.port}?//本網(wǎng)關(guān)注冊到Eureka的實(shí)例id

          3,啟用項(xiàng)目注冊到Eureka,并通過網(wǎng)關(guān)訪問Api 

          ?

          ?

          ?驗(yàn)證Api

          ?二,DotnetCore JWT證書頒布服務(wù)

          1,新建一個(gè)web api項(xiàng)目,Nuget添加:System.IdentityModel.Tokens.Jwt、Microsoft.IdentityModel.Tokens兩個(gè)包。配置文件添加jwt配置信息。

          appsetting.json 注意:Key用于jwt的簽名,長度不能少于16位。可用openssl生成一個(gè)32位的密鑰。

          "Identity":?{
          ???"Jwt":?{
          ?????"Key":?"1234567890123456",
          ?????"Domain":?"kingsun.mico"
          ???}
          ?}

          使用IOptions讀取配置信息并寫入依賴

          Startup.cs

          public?void?ConfigureServices(IServiceCollection?services)
          ????{
          ????????services.Configure(Configuration.GetSection("Identity"));
          ????????services.AddControllers();
          ????}

          2,新建一個(gè)名為Token的Api控制器并創(chuàng)建接口GetToken  

          [Route("api/[controller]")]
          ????[ApiController]
          ????public?class?TokenController?:?ControllerBase
          ????{
          ????????JwtConfig?config;
          ????????public?TokenController(IOptions?config)
          ????????{
          ????????????this.config?=?config.Value;
          ????????}
          ????????public?class?GetTokenRequest
          ????????{
          ????????????[Required]
          ????????????public?string?Name?{?get;?set;?}
          ????????????[Required]
          ????????????public?string?Password?{?get;?set;?}
          ????????}
          ????????public?class?GetTokenRespone
          ????????{
          ????????????public?int?Code?{?get;?set;?}
          ????????????public?string?Msg?{?get;?set;?}
          ????????????public?string?Data?{?get;?set;?}
          ????????}
          ????????[HttpPost("GetToken")]
          ????????public?object?GetToken([FromBody]?GetTokenRequest?data)
          ????????{
          ????????????GetTokenRespone?respone?=?new?GetTokenRespone()
          ????????????{
          ????????????????Code?=?0
          ????????????};
          ????????????if?(!ModelState.IsValid)
          ????????????{
          ????????????????respone.Msg?=?"用戶名或密碼不能為空";
          ????????????????return?respone;
          ????????????}
          ????????????//驗(yàn)證密碼邏輯
          ????????????//....
          ?
          ????????????//jwt中payload鍵值對內(nèi)容
          ????????????List?claims?=?new?List()
          ????????????{
          ????????????????//用戶名
          ????????????????new?Claim("name",data.Name)
          ????????????};
          ????????????var?key?=?new?SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(config.Jwt.Key));
          ????????????var?creds?=?new?SigningCredentials(key,SecurityAlgorithms.HmacSha256);
          ????????????var?token?=?new?JwtSecurityToken(
          ?????????????????issuer:?"liujb",?audience:?config.Jwt.Domain,?claims:?claims,?signingCredentials:?creds,?expires:DateTime.Now.AddDays(1),notBefore:DateTime.Now
          ????????????????);
          ????????????respone.Code?=?1;
          ????????????respone.Msg?=?"請求成功";
          ????????????respone.Data?=?new?JwtSecurityTokenHandler().WriteToken(token);
          ????????????return?respone;
          ????????}
          ????}

          3,獲取jwt令牌

            

          ?

          ?

          ?可拿此令牌驗(yàn)證后內(nèi)容如下:

          ?

          ?

          4,將此服務(wù)注冊到Eureka后用api網(wǎng)關(guān)轉(zhuǎn)發(fā)服務(wù)獲取token:http://localhost:8020/eureka-identity/api/token/gettoken

          {
          ????"code":?1,
          ????"msg":?"請求成功",
          ????"data":?"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoibGl1amIiLCJuYmYiOiIxNjAyODE3NjY1MjMwIiwiZXhwIjoiMTYwMjkwNDA2NTIzMCIsImlzcyI6ImxpdWpiIiwiYXVkIjoia2luZ3N1bi5taWNvIn0.5pIrNumEEy280-sCWp4d0K05Skc2Ptn1sK732Rw-L-A"
          }

          三,在api網(wǎng)關(guān)統(tǒng)一做接口認(rèn)證

          1,在第一步建立的網(wǎng)關(guān)項(xiàng)目中maven加入java-jwt依賴


          ???????????com.auth0
          ???????????java-jwt
          ???????????3.11.0
          ???????

          配置文件加入jwt密鑰:jwt.key=1234567890123456。值與第二步的中密鑰一致。

          2,在該項(xiàng)目新建一個(gè)全局過濾器。

          @Component
          public?class?JwtFilter?implements?GlobalFilter,?Ordered?{
          ????@Value("${jwt.key}")
          ????public?String?jwtKey;
          ????Logger?logger=null;
          ????public?JwtFilter(){
          ????????logger=?LoggerFactory.getLogger("JwtFilter");
          ????}
          ????@Override
          ????public?Mono?filter(ServerWebExchange?exchange,?GatewayFilterChain?chain)?{
          ????????String?requestUrl=exchange.getRequest().getPath().toString();
          ????????ServerHttpResponse?response?=?exchange.getResponse();
          ????????/*過濾掉獲取token的接口*/
          ????????if(requestUrl.toLowerCase().equals("/eureka-identity/api/token/gettoken")){
          ????????????return?chain.filter(exchange);
          ????????}
          ????????//獲取token
          ????????String?token=exchange.getRequest().getHeaders().getFirst("Authorization");
          ????????//沒有token返回未認(rèn)證
          ????????if(token==null||token==""){
          ????????????response.setStatusCode(HttpStatus.UNAUTHORIZED);
          ????????????return?response.setComplete();
          ????????}
          ????????try{
          ????????????this.getJwtByToken(token,jwtKey,null);
          ????????????return?chain.filter(exchange);
          ????????}
          ????????catch(Exception?ex){
          ????????????logger.error(ex.getMessage());
          ????????????response.setStatusCode(HttpStatus.UNAUTHORIZED);
          ????????????return?response.setComplete();
          ????????}
          ????}
          ?
          ????@Override
          ????public?int?getOrder()?{
          ????????return?0;
          ????}
          ????private?DecodedJWT?getJwtByToken(String?token,?String?key,?Map?claims)?throws?Exception{
          ????????Algorithm?algorithm?=?Algorithm.HMAC256(key);
          ????????Verification?verifier=?JWT.require(algorithm)
          ????????????????.withIssuer("liujb");
          ????????if(claims!=null){
          ????????????claims.forEach((mapKey,mapValue)->{
          ????????????????verifier.withClaim(mapKey,mapValue);
          ????????????});}
          ????????JWTVerifier?ver=?verifier.build();
          ????????DecodedJWT?jwt=ver.verify(token);
          ????????return?jwt;
          ????}
          }

          這里只做了簡單的認(rèn)證,以此基礎(chǔ)進(jìn)行深化,如根據(jù)不同的服務(wù)名稱要求不同的claim。 

          3,測試

          加入Authorization關(guān),值為之前獲取的jwt token

          ?

          ?如果token不對或沒有token都將返回401狀態(tài)值?

          ?




          粉絲福利:108本java從入門到大神精選電子書領(lǐng)取

          ???

          ?長按上方鋒哥微信二維碼?2 秒
          備注「1234」即可獲取資料以及
          可以進(jìn)入java1234官方微信群



          感謝點(diǎn)贊支持下哈?

          瀏覽 133
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  色老板在线观看永久 | 蜜桃视频在线入口www | 俺来也成人 | 亚洲日本中文字幕在线观看 | 黄色三级电影网站 |