zoukankan      html  css  js  c++  java
  • 基于IdentityServer4的单点登录——IdentityServer

    1.新建项目并添加引用

    新建一个asp .net core 2.0的项目
    引用IdentityServer4.AspNetIdentity

    2.定义资源

    新建Config.cs文件,定义Api资源与Identity资源
    资源分为身份资源(Identity resources)和API资源(API resources)

    (1)身份资源(Identity resources)

    身份资源是用户的用户名,姓名或电子邮件地址等数据。身份资源具有唯一的名称,可以为其分配任意声明类型。然后,这些声明将被包含在用户的身份令牌中。客户端将使用scope参数来请求访问身份资源。
    身份资源可以是IdentityServer自带的资源,也可以是自定义的资源。

    public static IEnumerable<IdentityResource> GetIdentityResources()
    {
        //自定义身份资源
        var customProfile = new IdentityResource(
            name: "custom.profile",
            displayName: "Custom profile",
            claimTypes: new[] { "name", "email", "status" });
        return new List<IdentityResource>
        {
            //IdentityServer自带的资源
            new IdentityResources.OpenId(),
            new IdentityResources.Profile(),
            customProfile
        };
    }
    

    (2)API资源(API resources)

    API资源是客户端访问API获得的资源

    public static IEnumerable<ApiResource> GetApiResources()
    {
        return new List<ApiResource>
        {
            //具有单一范围的简单API(在这种情况下,范围名称与api名称相同)
            new ApiResource("api1", "My API"),
            // 扩展版本,更多的设置选项
            new ApiResource
            {
                Name = "api2",
    
                // 用于内部校验的密码
                // ApiSecrets是用于内部校验的,API的名称(Name)和密码(ApiSecrets)可以用于认证
                ApiSecrets =
                {
                    new Secret("secret".Sha256())
                },
    
                // 在访问令牌中包含以下内容(除了subject ID)
                // UserClaims表示用户声明
                UserClaims = { JwtClaimTypes.Name, JwtClaimTypes.Email },
    
                // // 该API定义了两个范围
                Scopes =
                {
                    new Scope()
                    {
                        Name = "api2.full_access",
                        DisplayName = "Full access to API 2",
                    },
                    new Scope
                    {
                        Name = "api2.read_only",
                        DisplayName = "Read only access to API 2"
                    }
                }
            }
        };
    }
    

    3.定义客户端Client

    客户端指想要访问资源的Client

    public static IEnumerable<Client> GetClients()
    {
        return new List<Client>
        {
            //不一定要配置得这么复杂,根据需求来
            new Client
            {
                ClientId = "mvc",
                ClientName = "MVC Client",
                AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
    
                RequireConsent = true,
    
                ClientSecrets = 
                {
                    new Secret("secret".Sha256())
                },
                //这里配置客户端的网址,多个客户端则是多个网址
                RedirectUris = { "http://localhost:5002/signin-oidc" },
                PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },
                //允许的范围
                AllowedScopes =
                {
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,
                    "api1"
                },
                AllowOfflineAccess = true
            }
        };
    }
    

    其他配置请参阅:
    https://identityserver4.readthedocs.io/en/release/topics/clients.html

    4.配置

    把资源信息和客户端信息交给IdentityServer

    public void ConfigureServices(IServiceCollection services)
    {
        //配置服务
        services.AddIdentityServer()
            //读取客户端列表
            .AddInMemoryClients(Clients.Get())
            //读取身份资源列表
            .AddInMemoryIdentityResources(Resources.GetIdentityResources())
            //读取API资源列表
            .AddInMemoryApiResources(Resources.GetApiResources())
            //设置临时签名凭据
            .AddDeveloperSigningCredential()
            //添加测试用户
            .AddTestUsers(TestUsers.Users);
    }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        //配置管道:注意配置管道要写在路由的前面...
        app.UseIdentityServer();
    }
    

    这里需要注意的是,以上的资源信息和客户端信息是存在内存中的,可以设置为读取数据库
    参阅:https://identityserver4.readthedocs.io/en/release/quickstarts/8_entity_framework.html

    5.多客户端的统一登录

    (1)用户表

    //ApplicationUser继承于IdentityUser,可以在此为用户表添加属性,字段
    public class ApplicationUser : IdentityUser
    {
    }
    

    (2)页面

    <div class="col-md-4">
        <section>
            <form asp-route-returnurl="@ViewData["ReturnUrl"]" method="post">
                <h4>Use a local account to log in.</h4>
                <hr />
                <div asp-validation-summary="All" class="text-danger"></div>
                <div class="form-group">
                    <!--整个流程是根据邮箱进行注册和登录的-->
                    <label asp-for="Email"></label>
                    <input asp-for="Email" class="form-control" />
                    <span asp-validation-for="Email" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Password"></label>
                    <input asp-for="Password" class="form-control" />
                    <span asp-validation-for="Password" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <div class="checkbox">
                        <label asp-for="RememberMe">
                            <input asp-for="RememberMe" />
                            @Html.DisplayNameFor(m => m.RememberMe)
                        </label>
                    </div>
                </div>
                <div class="form-group">
                    <button type="submit" class="btn btn-default">Log in</button>
                </div>
                <div class="form-group">
                    <p>
                        <a asp-action="ForgotPassword">Forgot your password?</a>
                    </p>
                    <p>
                        <a asp-action="Register" asp-route-returnurl="@ViewData["ReturnUrl"]">Register as a new user?</a>
                    </p>
                </div>
            </form>
        </section>
    </div>
    

    (3)登录方法

    这里是AspNet Identity的内容

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
    {
        ViewData["ReturnUrl"] = returnUrl;
        if (ModelState.IsValid)
        {
            // 尝试登录
            // 需要注意的是,这里没有对登录失败进行计数
            // 为了在登录失败多次之后触发锁定用户,把lockoutOnFailure设置为true
            var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
            if (result.Succeeded)
            {
                _logger.LogInformation("User logged in.");
                return RedirectToLocal(returnUrl);
            }
            if (result.RequiresTwoFactor)
            {
                return RedirectToAction(nameof(LoginWith2fa), new { returnUrl, model.RememberMe });
            }
            if (result.IsLockedOut)
            {
                _logger.LogWarning("User account locked out.");
                return RedirectToAction(nameof(Lockout));
            }
            else
            {
                ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                return View(model);
            }
        }
        return View(model);
    }
    

    6.设置IdentityServer项目的端口号为5000

    7.其他

    整个流程还需要包括注册,注销,忘记密码,第三方登录,修改用户信息等,这些不属于IdentityServer的讨论范畴,在此不做讨论

  • 相关阅读:
    地址路由使用
    SpringMVC的各种参数绑定方式
    SpringMVC 的 Controller 返回各种视图的处理方式
    jQuery过滤选择器:not()方法使用介绍
    js数组的操作
    ligerui grid行编辑示例
    ilter()和find()的区别
    java 文件字节输出流
    java 文件字节输入流
    java 创建一个File文件对象
  • 原文地址:https://www.cnblogs.com/Lulus/p/7986635.html
Copyright © 2011-2022 走看看