Asp.Net WebApi 接入Identity Server4 全记录

Asp.Net WebApi 接入Identity Server4 全记录

当前环境

  1. Net Core 2.2+ //建议使用Net Core 3.0

  2. Asp.Net Framework 4.6.2+

  3. Visual Studio 2019//如果使用Net Core 3.0,你可能需要预览版

新增空的解决方案

  1. 打开命令行。执行dotnet new sln -n SsoTest 建立空白解决方案。

新增Identity Server4 服务端【本文不讨论服务端配置问题】

新增项目并添加到解决方案里

  1. 打开命令行或者powershell

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # 新增IdentityServer4模板
    dotnet new -i IdentityServer4.Templates
    # 新建项目
    dotnet new is4empty -n IdentityServer
    # 添加到解决方案
    dotnet sln add .\IdentityServer\IdentityServer.csproj
    # 进入项目目录
    cd IdentityServer
    # 添加UI
    dotnet new is4ui
  2. 修改Config.cs文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    using IdentityServer4;
    using IdentityServer4.Models;
    using IdentityServer4.Test;
    using System.Collections.Generic;
    using System.Security.Claims;

    namespace IdentityServer
    {
    public static class Config
    {
    public static IEnumerable<IdentityResource> GetIdentityResources()
    {
    return new IdentityResource[]
    {
    new IdentityResources.OpenId(),
    new IdentityResources.Profile(),
    new IdentityResources.Email(),
    new IdentityResources.Phone(),
    };
    }
    public static List<TestUser> GetUsers()
    {
    return new List<TestUser> {
    new TestUser {
    SubjectId = "1",
    Username = "alice",
    Password = "password",
    Claims = new []
    {
    new Claim("name", "Alice"),
    new Claim("website", "https://alice.com")
    }
    },
    new TestUser {
    SubjectId = "2",
    Username = "bob",
    Password = "password",
    Claims = new []
    {
    new Claim("name", "Bob"),
    new Claim("website", "https://bob.com")
    }
    }
    };
    }
    public static IEnumerable<ApiResource> GetApis()
    {
    return new ApiResource[] {
    new ApiResource ("api1", "My API")
    };
    }

    public static IEnumerable<Client> GetClients()
    {
    var secret = "49C1A7E1-0C79-4A89-A3D6-A37998FB86B0".Sha256();
    return new Client[] {
    new Client {
    ClientId = "mvc",
    ClientName = "MVC Client",
    ClientSecrets = {
    new Secret (secret)
    },
    AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
    // where to redirect to after login
    RedirectUris = { "http://localhost:5001/signin-oidc" },
    // where to redirect to after logout
    PostLogoutRedirectUris = { "http://localhost:5001/signout-callback-oidc" },
    AllowedScopes = new List<string> {
    IdentityServerConstants.StandardScopes.OpenId,
    IdentityServerConstants.StandardScopes.Email,
    IdentityServerConstants.StandardScopes.Phone,
    IdentityServerConstants.StandardScopes.Profile,
    "api1"
    }
    },,
    new Client
    {
    ClientName = "vuejs",
    ClientId = "vuejsclient",
    AllowedGrantTypes=GrantTypes.Implicit,
    AllowAccessTokensViaBrowser=true,
    AccessTokenType = AccessTokenType.Reference,
    UpdateAccessTokenClaimsOnRefresh = true,
    AllowOfflineAccess = true,
    RequireConsent = false,
    //AccessTokenLifetime = 50,
    RedirectUris = new List<string>()
    {
    "http://localhost:5002/static/callback.html",
    "http://localhost:5002/static/silent-renew.html"
    },
    PostLogoutRedirectUris = {
    "http://localhost:5002/index.html"
    },
    AllowedCorsOrigins = {
    "http://localhost:5002"
    },
    AllowedScopes =
    {
    IdentityServerConstants.StandardScopes.OpenId,
    IdentityServerConstants.StandardScopes.Profile,
    IdentityServerConstants.StandardScopes.Address,
    "roles",
    "identityserver4api",
    "country",
    "subscriptionlevel"
    },
    ClientSecrets =
    {
    new Secret("secret".Sha256())
    }
    }
    };
    }
    }
    }
  3. 修改Startup.cs,取消注释

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    public IHostingEnvironment Environment { get; }

    public Startup(IHostingEnvironment environment)
    {
    Environment = environment;
    }

    public void ConfigureServices(IServiceCollection services)
    {
    // uncomment, if you want to add an MVC-based UI
    services.AddMvc().SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_2_1);

    var builder = services.AddIdentityServer()
    .AddInMemoryIdentityResources(Config.GetIdentityResources())
    .AddInMemoryApiResources(Config.GetApis())
    .AddInMemoryClients(Config.GetClients())
    .AddTestUsers(Config.GetUsers());

    if (Environment.IsDevelopment())
    {
    builder.AddDeveloperSigningCredential();
    }
    else
    {
    throw new Exception("need to configure key material");
    }
    }

    public void Configure(IApplicationBuilder app)
    {
    if (Environment.IsDevelopment())
    {
    app.UseDeveloperExceptionPage();
    }

    // uncomment if you want to support static files
    app.UseStaticFiles();

    app.UseIdentityServer();
    // uncomment, if you want to add an MVC-based UI
    app.UseMvcWithDefaultRoute();
    }
  4. 新开一个命令行或者powershell窗口,运行服务端

    1
    2
    3
    4
    5
    6

    # 还原nuget,编译
    dotnet restore
    dotnet build
    # 运行
    dotnet run

新增一个空的WebApi项目

  1. 打开解决方案SsoTest.sln
  2. 在解决方案上右键->添加->新建项目,创建WebApi项目,名为SSOTest.WebApi



配置WebApi接入Identity Server

  1. 修改项目属性,指定web端口为5002

  2. 打开包控制台,安装nuget包

    1
    2
    3
    Install-Package IdentityModel -Version 3.10.10
    Install-Package IdentityServer3.Contrib.AccessTokenValidation
    Install-Package Microsoft.Owin.Host.SystemWeb
  3. 新增OWIN的Startup.cs文件

  4. 修改为Startup.cs文件.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    using System;
    using System.Net.Http;
    using System.Security.Claims;
    using System.Web.Helpers;
    using IdentityModel;
    using IdentityModel.Client;
    using Microsoft.Owin;
    using Microsoft.Owin.Security;
    using Microsoft.Owin.Security.Cookies;
    using Microsoft.Owin.Security.OpenIdConnect;
    using Owin;

    [assembly: OwinStartup(typeof(SSOTest.Client.Startup))]

    namespace SSOTest.Client
    {
    public partial class Startup
    {
    public void Configuration(IAppBuilder app)
    {
    // 有关如何配置应用程序的详细信息,请访问 https://go.microsoft.com/fwlink/?LinkID=316888
    ConfigureAuth(app);
    }

    private void ConfigureAuth(IAppBuilder app)
    {
    var secret = "49C1A7E1-0C79-4A89-A3D6-A37998FB86B0".ToSha256();
    AntiForgeryConfig.UniqueClaimTypeIdentifier = "sub";
    app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
    {
    Authority = "http://localhost:5000",
    RequiredScopes = new string[] { "webapi" },
    ClientId = "Test",
    ClientSecret = secret,
    DelayLoadMetadata = true
    });
    }
    }
    }
  5. 打开Controllers/ValuesController.cs
    Get这个Action上加特性[Authorize]

  6. 运行Client项目,访问 http://localhost:5002/Api/Values

源码下载

on the github