欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

.net core使用ocelot---第二篇 身份验证

程序员文章站 2022-05-30 18:18:12
简介原文链接 .net core使用ocelot 第一篇 简单使用 接上文,我将继续介绍使用asp.net core 创建API网关,主要介绍身份验证(authentication )相关内容。 API服务是需要保护的资源,我们应该尽可能的保证他们的安全。 通常,我们会使用aspnet securi ......

简介

      

         接上文,我将继续介绍使用asp.net core 创建api网关,主要介绍身份验证(authentication )相关内容。

         api服务是需要保护的资源,我们应该尽可能的保证他们的安全。

         通常,我们会使用aspnet security 来保证我们项目的安全,aspnet security代码库是为asp.net core 设计的安全和授权中间件。已经让事情变得简单。

         那么我们在项目中引入api网关会不会导致巨大的改变?答案是,不会。我们的修改微乎其微,但是却让安全和授权变得简单。

         先看下面的截图。

.net core使用ocelot---第二篇 身份验证

  截图显示,当我们访问我们的服务,api网关会让我们首先访问其授权模块。我们必须访问授权服务获得访问令牌(access token),然后用访问令牌访问受保护的服务。

         可能你倾向将授权服务独立,这意味客户端得先访问授权服务获得访问令牌。然后携带令牌访问api网关。毫无疑问这样做没问题,但是我建议将授权服务和其他服务放在一起。

         apigateway是我们所有服务的入口,对于身份未验证的客户端仅可以访问授权服务。

         ok,开始我们的表演。

         我会使用上一个demo的部分内容,便于理解。

step1

项目名称

项目类型

描述

apigateway

asp.net core empty

示例的入口

customersapiservices

asp.net core web api

api 服务处理消费者的操作

authserver

asp.net core web api

api 服务处理授权操作

clientapp

console app

控制台程序模拟客户端

  apigateway和customerapiservices和上篇文章的例子一样,你可以在apigatewaybasicdemo获得。

step2

         创建authserver,authserver主要是为request请求生成访问令牌(access token),我们需要添加一个方法处理。

[httpget]  
public iactionresult get(string name, string pwd)  
{  
    //just hard code here.  
    if (name == "catcher" && pwd == "123")  
    {  
        var now = datetime.utcnow;  
  
        var claims = new claim[]  
        {  
            new claim(jwtregisteredclaimnames.sub, name),  
            new claim(jwtregisteredclaimnames.jti, guid.newguid().tostring()),  
            new claim(jwtregisteredclaimnames.iat, now.touniversaltime().tostring(), claimvaluetypes.integer64)  
        };  
  
        var signingkey = new symmetricsecuritykey(encoding.ascii.getbytes(_settings.value.secret));  
        var tokenvalidationparameters = new tokenvalidationparameters  
        {  
            validateissuersigningkey = true,  
            issuersigningkey = signingkey,  
            validateissuer = true,  
            validissuer = _settings.value.iss,  
            validateaudience = true,  
            validaudience = _settings.value.aud,  
            validatelifetime = true,  
            clockskew = timespan.zero,  
            requireexpirationtime = true,  
  
        };  
  
        var jwt = new jwtsecuritytoken(  
            issuer: _settings.value.iss,  
            audience: _settings.value.aud,  
            claims: claims,  
            notbefore: now,  
            expires: now.add(timespan.fromminutes(2)),  
            signingcredentials: new signingcredentials(signingkey, securityalgorithms.hmacsha256)  
        );  
        var encodedjwt = new jwtsecuritytokenhandler().writetoken(jwt);  
        var responsejson = new  
        {  
            access_token = encodedjwt,  
            expires_in = (int)timespan.fromminutes(2).totalseconds  
        };  
  
        return json(responsejson);  
    }  
    else  
    {  
        return json("");  
    }  
}  

  在验证用户时。我使用硬编码将用户名写死,因为对于本文这个不是那么重要。

  这样我们就完成了授权服务,现在跑起来。

.net core使用ocelot---第二篇 身份验证

step3

         回到customersapiservices项目,我们应该保护这个服务。

         修改startup,我们可以使用授权。在这我用jwtbearer进行授权,我会给testkey设置默认的授权方案。testkey我将在下面提到。

public void configureservices(iservicecollection services)  
{  
    var audienceconfig = configuration.getsection("audience");  
  
    var signingkey = new symmetricsecuritykey(encoding.ascii.getbytes(audienceconfig["secret"]));  
    var tokenvalidationparameters = new tokenvalidationparameters  
    {  
        validateissuersigningkey = true,  
        issuersigningkey = signingkey,  
        validateissuer = true,  
        validissuer = audienceconfig["iss"],  
        validateaudience = true,  
        validaudience = audienceconfig["aud"],  
        validatelifetime = true,  
        clockskew = timespan.zero,  
        requireexpirationtime = true,  
    };  
  
    services.addauthentication()  
            .addjwtbearer("testkey", x =>  
             {  
                 x.requirehttpsmetadata = false;  
                 x.tokenvalidationparameters = tokenvalidationparameters;  
             });  
  
    services.addmvc();  
}  
public void configure(iapplicationbuilder app)  
{              
    app.useauthentication();  
    app.usemvc();  
} 

  接下来,对需要保护的方法,添加authorize。

[authorize]  
[httpget]  
public ienumerable<string> get()  
{  
    return new string[] { "catcher wong", "james li" };  
}  

注意

         该项目基于asp.net core 2.0. 如果你的项目是1.x,可能有些不同,建议用迁移到2.0.以上。接下来就是见证奇迹的时候了。

.net core使用ocelot---第二篇 身份验证

step4

         最重要的步骤来了,在apigateway中配置授权。

public void configureservices(iservicecollection services)  
{  
    var audienceconfig = configuration.getsection("audience");  
  
    var signingkey = new symmetricsecuritykey(encoding.ascii.getbytes(audienceconfig["secret"]));  
    var tokenvalidationparameters = new tokenvalidationparameters  
    {  
        validateissuersigningkey = true,  
        issuersigningkey = signingkey,  
        validateissuer = true,  
        validissuer = audienceconfig["iss"],  
        validateaudience = true,  
        validaudience = audienceconfig["aud"],  
        validatelifetime = true,  
        clockskew = timespan.zero,  
        requireexpirationtime = true,  
    };  
  
    services.addauthentication()  
            .addjwtbearer("testkey", x =>  
             {  
                 x.requirehttpsmetadata = false;  
                 x.tokenvalidationparameters = tokenvalidationparameters;  
             });  
  
    services.addocelot(configuration);  
}  

 

  这个配置的大部分代码和customer service一样。

  当ocelot启动,它会查看reroutes 》authenticationoptions 》authenticationproviderkey 的值,

检查该值是否被授权服务注册,如果没有,ocelot不会启动,如果有,ocelot在执行时使用授权服务。

         所以,我们得修改configuration.json,我们需要添加新的节点,并将其值赋为在startup 类中定义的一样。

{  
    "downstreampathtemplate": "/api/customers",  
    "downstreamscheme": "http",  
    "downstreamhost": "localhost",  
    "downstreamport": 9001,  
    "upstreampathtemplate": "/customers",  
    "upstreamhttpmethod": [ "get" ],  
    "authenticationoptions": {  
        "authenticationproviderkey": "testkey",  
        "allowedscopes": []  
    }  
}  

  启动服务。

 

.net core使用ocelot---第二篇 身份验证

注意

         当你启动项目时遇到下面的错误,你应该检查你的代码,查看addjwtbearer 方法是否指明授权方案。

        unhandled exception: system.invalidoperationexception: scheme already exists: bearer

step5

         我们已经准备完毕,我们用我们的客户端模拟apigateway的某些请求。

 

         我们先添加获得访问令牌的方法。

private static string getjwt()  
{  
    httpclient client = new httpclient();  
    client.baseaddress = new uri( "http://localhost:9000");  
    client.defaultrequestheaders.clear();  
    var res2 = client.getasync("/api/auth?name=catcher&pwd=123").result;  
    dynamic jwt = jsonconvert.deserializeobject(res2.content.readasstringasync().result);  
    return jwt.access_token;  
} 

 

 接下来,编写通过apigateway访问customer service方法的代码。

static void main(string[] args)  
{  
    httpclient client = new httpclient();  
      
    client.defaultrequestheaders.clear();  
    client.baseaddress = new uri("http://localhost:9000");  
      
    // 1. without access_token will not access the service  
    //    and return 401 .  
    var reswithouttoken = client.getasync("/customers").result;  
      
    //print something here   
      
    //2. with access_token will access the service  
    //   and return result.  
    client.defaultrequestheaders.clear();  
    var jwt = getjwt();  
      
    client.defaultrequestheaders.add("authorization", $"bearer {jwt}");  
    var reswithtoken = client.getasync("/customers").result;  
      
    //print something here   
      
    //3. visit no auth service   
    client.defaultrequestheaders.clear();  
    var res = client.getasync("/customers/1").result;  
      
    //print something here   
      
    console.read();  
}  

 

运行结果。

.net core使用ocelot---第二篇 身份验证

 

  完工。

  源码在此

总结

         没啥。