zoukankan      html  css  js  c++  java
  • 4. 使用IdentityServer4 实现 基于OIDC 的内部MVC客户端认证

    1. 概述

    • 上一个实例 中实现了简单的 ResourceOwnerPassword 授权.

    • 本例将使用IdentityServer4 实现内部系统的单点登录,让组织内部的MVC 客户端使用认证中心的登录页实现登录,使用的是OAuth2 的隐式授权码模式Implicit AthorizationCode

    • MVC 客户端集成IdentityServer4 认证时,为简单起见,将使用cookie存储客户端凭据;同时启用IdentityServer4 内置的 OpenIdConnect(OIDC)身份认证服务。

    2. 关键概念

    • IdentityResource : OIDC 协议中定义的身份认证资源,这种资源具有唯一名称,资源声明后将包含在用户的身份令牌中。参考: https://docs.identityserver.io/en/3.1.0/topics/resources.html

    • IIdentityServerInteractionService : 这是IdentityServer4提供的认证交互接口。

    3. 准备MVC Web客户端

    新建一个MVCClient 项目,设置访问地址和端口为:http://localhost:5030。
    

    3.1 引用依赖包

     <PackageReference Include="IdentityServer4" Version="4.1.1" />
    

    3.2 注册OIDC 服务,并启用认证中间件

    // DI容器中注册服务
    services.AddAuthentication(opt =>
                {
                    opt.DefaultScheme = "Cookies";
                    opt.DefaultChallengeScheme = "oidc";
                }).AddCookie("Cookies")
                .AddOpenIdConnect("oidc", options =>
                {
                    options.SignInScheme = "Cookies";
                    options.Authority = "http://localhost:5010";
                    options.RequireHttpsMetadata = false;
    
                    options.ClientId = "mvc";
                    options.SaveTokens = true;
                });
    
    // ConfigureService 中启用中间件
                app.UseAuthentication();
    
    // 将受保护页面使用【Authorize】 保护起来,访问首页时将重定向到Account/Login
     [Authorize]
        public class HomeController : Controller
    {
    ……  ……
    }
    

    4. 服务端配置

    4.1 添加IdentityResource(在server端的Config 类中添加) 和client

            public static List<IdentityResource> GetIdentityResources()
            {
                var result = new List<IdentityResource>
                {
                    new IdentityResources.OpenId(),
                    new IdentityResources.Profile()
                };
                return result;
            }
    
    // 新增一个client
               new Client
                {
                    ClientId="mvc",
                    ClientName="MVC Client",
                    RequireConsent=false,
                    AllowedGrantTypes= GrantTypes.Implicit, // 隐式授权码
                    RedirectUris={"http://localhost:5030/signin-oidc"}, // 这里的回调地址是MVC客户端的地址
                    PostLogoutRedirectUris={"http://localhost:5030/signout-callback-oidc"},
                    AllowedScopes= new List<string>
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile
                    }
    
                }
    
    // Startup 注册IdentityResource
    
    services.AddIdentityServer()
                    .AddDeveloperSigningCredential()
                    .AddInMemoryApiResources(Config.GetApiResources)
                    .AddInMemoryIdentityResources(Config.GetIdentityResources())
                    .AddInMemoryClients(Config.GetClients)
                    .AddInMemoryApiScopes(Config.GetApiScopes) // 3.1 新增的坑,不加会报invalid_scope
                    .AddTestUsers(Config.GetTestUsers())
                    ;
    
    

    5. 测试验证

    启动服务端5010,和客户端5030 此时客户端将重定向到5010 的登录页Account/Login

    可以输入TestUsers中配置的用户名密码登录

    5.1 Account/Login 的登录方法

           [HttpPost]
            public async Task<IActionResult> Login(LoginViewModel model, string returnUrl)
            {
                ViewData["ReturnUrl"] = returnUrl;
                var user = _users.FindByUsername(model.UserName);
    
                if (user == null)
                {
                    ModelState.AddModelError(nameof(model.UserName), "User not exists.");
                }
                else
                {
                    if (_users.ValidateCredentials(model.UserName, model.Password))
                    {
                        var props = new AuthenticationProperties
                        {
                            IsPersistent = true,
                            ExpiresUtc = DateTimeOffset.UtcNow.Add(TimeSpan.FromMinutes(30))
                        };
                        var u = new IdentityServerUser(user.SubjectId) { DisplayName = user.Username };
    
                        await Microsoft.AspNetCore.Http.AuthenticationManagerExtensions.SignInAsync(
                              this.HttpContext,
                              u,
                              props);
                        return Redirect(returnUrl);
                    }
                }
                return View();
    
            }
    
  • 相关阅读:
    selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
    ERROR: virtualenvwrapper could not find virtualenv in your path
    VM中的Centos 7配置静态IP
    CentOS7 安装JumpServer
    ERROR 1130 (HY000): Host 'test177' is not allowed to connect to this MySQL server
    获取到一张表中指定字段重复的数量
    Windows7设置局域网文件共享
    vmware虚拟机安装Windows 7后虚拟机自动挂起
    关于PHP版本比较函数version_compare的问题
    关于数据表中一对多、多对一关系的设计
  • 原文地址:https://www.cnblogs.com/aimigi/p/13943748.html
Copyright © 2011-2022 走看看