Coder Social home page Coder Social logo

usemvc5connectidentity4's Introduction

title date tags
Asp.Net MVC接入Identity Server4 全记录
2019-09-20 10:40
Asp.Net MVC Identity Server

Asp.Net MVC接入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

    # 新增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文件

    using IdentityServer4;
    using IdentityServer4.Models;
    using IdentityServer4.Test;
    using System.Collections.Generic;
    using System.Security.Claims;https://github.com/xyfy/UseMvc5ConnectIdentity4/blob/master/readme.md
    
    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"
                        }
                    }};
            }
        }
    }
  3. 修改Startup.cs,取消注释

        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窗口,运行服务端

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

新增一个空的MVC5项目

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

配置MVC5接入Identity Server

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

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

    Install-Package IdentityModel -Version 3.10.10
    Install-Package Microsoft.Owin.Security.Cookies
    Install-Package Microsoft.Owin.Security.OpenIdConnect
    Install-Package Microsoft.Owin.Host.SystemWeb
  3. 新增OWIN的Startup.cs文件

  4. 修改为Startup.cs文件.

    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)
            {
                ConfigureAuth(app);
            }
    
            public void ConfigureAuth(IAppBuilder app)
            {
                AntiForgeryConfig.UniqueClaimTypeIdentifier = "sub";
    
                app.UseCookieAuthentication(new CookieAuthenticationOptions
                {
                    AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
                    CookieHttpOnly = true
                });
                var secret = "49C1A7E1-0C79-4A89-A3D6-A37998FB86B0".ToSha256();
                app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
                {
                    Authority = "http://localhost:5000",
                    ClientId = "mvc",
                    ClientSecret = secret,
                    RedirectUri = "http://localhost:5001/signin-oidc",
                    PostLogoutRedirectUri = "http://localhost:5001/signout-oidc",
                    ResponseType = "code id_token",
                    Scope = "openid profile",
                    RequireHttpsMetadata = false,
                    SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
                    Notifications = new OpenIdConnectAuthenticationNotifications
                    {
                        AuthorizationCodeReceived = async n =>
                        {
                            var client = new HttpClient();
                            var disco = await client.GetDiscoveryDocumentAsync(new DiscoveryDocumentRequest()
                            {
                                Address = "http://localhost:5000",
                                Policy ={
                                    RequireHttps = false
                                }
                            });
                            if (disco.IsError) throw new Exception(disco.Error);
                            // use the code to get the access and refresh token
                            var tokenResponse = await client.RequestAuthorizationCodeTokenAsync(new AuthorizationCodeTokenRequest()
                            {
                                Address = disco.TokenEndpoint,
                                ClientId = "mvc",
                                ClientSecret = "49C1A7E1-0C79-4A89-A3D6-A37998FB86B0",
                                Code = n.Code,
                                RedirectUri = n.RedirectUri
                            });
    
                            if (tokenResponse.IsError)
                            {
                                throw new Exception(tokenResponse.Error);
                            }
                            // use the access token to retrieve claims from userinfo
                            var userInfoResponse = await client.GetUserInfoAsync(new UserInfoRequest()
                            {
                                Address = disco.UserInfoEndpoint,
                                Token = tokenResponse.AccessToken
                            });
    
                            // create new identity
                            var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
                            id.AddClaims(userInfoResponse.Claims);
                            id.AddClaim(new Claim("access_token", tokenResponse.AccessToken));
                            id.AddClaim(new Claim("expires_at", DateTime.UtcNow.AddSeconds(tokenResponse.ExpiresIn).ToString()));
                            //id.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken));
                            id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                            id.AddClaim(new Claim("sid", n.AuthenticationTicket.Identity.FindFirst("sid").Value));
    
                            n.AuthenticationTicket = new AuthenticationTicket(
                                        new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType, "name", "role"),
                                        n.AuthenticationTicket.Properties);
                            //TODO 本地USER同步
                            foreach (var item in userInfoResponse.Claims)
                            {
                                if (item.Type == "sub")
                                {
                                }
                            }
                        }
                    }
                });
            }
        }
    }
  5. 打开Controllers/HomeController.cs 在About这个Action上加特性[Authorize]

  6. 运行Client项目,访问 http://localhost:5001/Home/About

源码下载

on the github

usemvc5connectidentity4's People

Contributors

dependabot[bot] avatar xyfy avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.