WebAPI IdentityServer4身份验证及客户端访问实现

2018/04/20 16:38
阅读数 135
 根据博客园 solenovex的《 使用Identity Server 4建立Authorization Server》系列,老菜测试Asp.Net Core 2.0 WebAPI及IdentityServer4身份验证 ,并实现客户端访问。
 
 
 
1、 打开VS2017,新建项目,选择 .net core->ASP.NET Core Web应用程序,项目名称为MyWebAPI,选择WebAPI,完成项目创建。
2、工具菜单选择Nuget包管理,打开“管理解决方案的NuGet包”,查找并安装IdentityServer4和IdentityServer4.AccessTokenValida。
3、修改项目配置launchSettings.json:
 
 
    "profiles": {
        "MyWebAPI": {
            "commandName": "Project",
            "launchBrowser": true,
            "environmentVariables": {
                "ASPNETCORE_ENVIRONMENT": "Development"
            },
            "applicationUrl": "http://localhost:6000/"
        }
    }   
}
 
4、项目中建立Configuration目录,建InMemoryConfiguration.cs:
 
 
 
 
 
using IdentityServer4;
using IdentityServer4.Models;
using IdentityServer4.Test;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
 
namespace MyWebAPI.Configuration
{
    public class InMemoryConfiguration
    {
        public static IEnumerable<IdentityResource> GetIdentityResources()
        {
            return new List<IdentityResource>
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),
               
            };
        }
        public static IEnumerable<ApiResource> ApiResources()
        {
            return new[]
            {
                new ApiResource("socialnetwork", "社交网络")
                {
                    UserClaims = new [] { "email" }
                }
            };
        }
 
        public static IEnumerable<Client> Clients()
        {
            return new[]
            {
                new Client
                {
                    ClientId = "socialnetwork",
                    ClientSecrets = new [] { new Secret("secret".Sha256()) },
                    AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,
                    AllowedScopes = new [] { "socialnetwork" }
                }
            };
                
        }
 
        public static IEnumerable<TestUser> Users()
        {
            return new[]
            {
                new TestUser
                {
                    SubjectId = "1",
                    Username = "mail@qq.com",
                    Password = "password",
                    Claims = new [] { new Claim("email", "mail@qq.com") }
                }
            };
        }
    }
}
 
5、 修改Startup.cs中的ConfigureServices
 
public void ConfigureServices(IServiceCollection services)
{
    services.AddIdentityServer()
         .AddDeveloperSigningCredential()
         .AddInMemoryIdentityResources(InMemoryConfiguration.GetIdentityResources())
         .AddTestUsers(InMemoryConfiguration.Users().ToList())
         .AddInMemoryClients(InMemoryConfiguration.Clients())
         .AddInMemoryApiResources(InMemoryConfiguration.ApiResources());
   
 
    services.AddMvcCore()
    .AddAuthorization()
    .AddJsonFormatters();
 
    services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
 {
     options.RequireHttpsMetadata = false;
     options.Authority = "http://localhost:6000";
     options.ApiName = "socialnetwork";
 });
}
 
 
 
6、修改Startup.cs中的Configure
 
public void Configure(IApplicationBuilder app, IHostingEnvironment env)        
{
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }  
            app.UseIdentityServer();
            app.UseStaticFiles();
            app.UseAuthentication();
            app.UseMvcWithDefaultRoute();
            
}
 
 
7、修改示例API控制器——ValuesController
 
 
[Authorize]
[Route("api/[controller]")]
public class ValuesController : Controller
{
     // GET api/values
     [HttpGet]
public JsonResult Get()
{
  JsonResult a = new JsonResult(new string[]{ "value1", "value2" });
  return a;
     }
}
 
8、运行项目,弹出dotnet console窗体,并在项目根目录生成临时证书tempkey.rsa
 
9、运行Postman,在builder中创建POST标签窗口,POST测试获取token
 
 
 
 
即可获得token。
 
10、客户端之一(IdentityModel): 新建.net Core 2 console控制台应用项目MyClient。通过“管理解决方案的NuGet包”,查找并安装IdentityModel包。 代码如下:
 
 
using IdentityModel.Client;
using Newtonsoft.Json.Linq;
using System;
using System.Net.Http;
using System.Threading.Tasks;
 
namespace MyClient
{
    class Program
    {
        public static void Main(string[] args) => MainAsync().GetAwaiter().GetResult(); 
        private static async Task MainAsync()
        {
            //DiscoveryClient类:IdentityModel提供给我们通过基础地址(如:http://localhost:6000)
            //就可以访问令牌服务端;当然可以根据上面的restful api里面的url自行构建;上面就是通过基础地址,
            //获取一个TokenClient;(对应restful的url:token_endpoint= "http://localhost:6000/connect/token")
 
            var dico = await DiscoveryClient.GetAsync("http://localhost:6000");
 
            //token
            var tokenClient = new TokenClient(dico.TokenEndpoint, "socialnetwork", "secret");
            var tokenresp = await tokenClient.RequestClientCredentialsAsync("socialnetwork");
            if (tokenresp.IsError)
            {
                Console.WriteLine(tokenresp.Error);
                return;
 
            }
 
            Console.WriteLine(tokenresp.Json);
            Console.WriteLine("\n\n");
 
 
            var client = new HttpClient();
            client.SetBearerToken(tokenresp.AccessToken);
            var resp = await client.GetAsync("http://localhost:6000/api/values");
            //var resp = await client.GetAsync("http://localhost:6000/identity");
            if (!resp.IsSuccessStatusCode)
            {
                Console.WriteLine(resp.StatusCode);
            }
            else
            {
                var content = await resp.Content.ReadAsStringAsync();
                Console.WriteLine(JArray.Parse(content));
            }
 
            Console.ReadKey(true);
 
 
        }
    }
}
结果:
 
 
 
 
11、客户端之一(Restsharp),另外新建.net Core 2 console控制台应用项目MyjwtClient。通过“管理解决方案的NuGet包”,查找并安装Restsharp、Newtonsoft.Json包。 代码如下:
 
 
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RestSharp;
using RestSharp.Authenticators;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace MyClient
{
    class Program
    {
        /// <summary>
        /// 访问Url
        /// </summary>
        static string _url = "http://localhost:6000";
        static void Main(string[] args)
        {
            var client = new RestClient(_url);
 
            RestRequest request = CreatePostTokenRestRequest(client);
 
            var response = client.Execute(request);
            JObject jo = (JObject)JsonConvert.DeserializeObject(response.Content);
 
            Console.WriteLine(response.Content);
 
            string access_token = jo["access_token"].ToString();
 
            RestRequest requestapi = CreateGetApiRestRequestByToken(access_token);
            var responseapi = client.Execute(requestapi); 
 
            Console.WriteLine(responseapi.Content);
              
            Console.ReadKey(true);
 
        }
 
        private static RestRequest CreateGetApiRestRequestByToken(string access_token)
        {
            RestRequest requestapi = new RestRequest() { Method = Method.GET };
 
            requestapi.AddHeader("Content-Type", "application/x-www-form-urlencoded");
            requestapi.AddHeader("Accept", "application/json");
            requestapi.AddHeader("authorization", string.Format("Bearer {0}", access_token));
 
            requestapi.Resource = "/api/values";
            return requestapi;
        }
 
        private static RestRequest CreatePostTokenRestRequest(RestClient client)
        {
            RestRequest request = new RestRequest() { Method = Method.POST }; 
            client.Authenticator = new HttpBasicAuthenticator("socialnetwork", "secret"); 
            request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
            request.AddHeader("Accept", "application/json");
            request.AddParameter("client_id", "socialnetwork");
            request.AddParameter("client_secret", "secret");
            request.AddParameter("grant_type", "password");
            request.AddParameter("username", "mail@qq.com");
            request.AddParameter("password", "password");
            request.Resource = "/connect/token";
            return request;
        }
 
        private static RestRequest CreatePostRefresfTokenRestRequest(RestClient client)
        {
            RestRequest request = new RestRequest() { Method = Method.POST };
            client.Authenticator = new HttpBasicAuthenticator("socialnetwork", "secret");
            request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
            request.AddHeader("Accept", "application/json");
            request.AddParameter("client_id", "mvc_code");
            request.AddParameter("client_secret", "secret");
            request.AddParameter("grant_type", "hybird");
            request.AddParameter("username", "mail@qq.com");
            request.AddParameter("password", "password");
            request.Resource = "/connect/token";
            return request;
        }
    }
}
 
12、先运行MyWebApi,后运行MyClient
 
 
在MyClient中通过RestRequest获取response,通过JsonConvert.DeserializeObject解析response内容中的access_token,然后通过创建WebAPI请求的RestRequest,根据access_token,获得webapi的返回值。
展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部