zoukankan      html  css  js  c++  java
  • ASP.NET Core分布式项目实战(oauth2 + oidc 实现 server部分)--学习笔记

    任务15:oauth2 + oidc 实现 server部分

    基于之前快速入门的项目(MvcCookieAuthSample):
    https://www.cnblogs.com/MingsonZheng/p/11614686.html
    https://www.cnblogs.com/MingsonZheng/p/11623815.html

    mvcCookieAuthSample2下载地址:
    http://video.jessetalk.cn/course/5/material/217/download

    把这个 MVC 注册登录的网站变成一个单点登录,现在它是自己登录自己使用,我们需要把它的登录信息返回给第三方

    添加 identityserver4 引用

    在 startup 中

    using IdentityServer4;
    

    按照之前的文章添加 Config.cs

    using System.Collections;
    using System.Collections.Generic;
    using IdentityServer4.Models;
    using IdentityServer4.Test;
    
    namespace mvcCookieAuthSample
    {
        public class Config
        {
            public static IEnumerable<Client> GetClients()
            {
                return new List<Client>
                {
                    new Client()
                    {
                        ClientId = "client",
                        AllowedGrantTypes = GrantTypes.Implicit,// 隐式模式
                        ClientSecrets = 
                        {
                            new Secret("secret".Sha256())
                        },
                        AllowedScopes = {"api"},
                    }
                };
            }
    
            public static IEnumerable<ApiResource> GetApiResource()
            {
                return new List<ApiResource>
                {
                    new ApiResource("api", "My Api")
                };
            }
    
            public static IEnumerable<IdentityResource> GetIdentityResources()
            {
                return new List<IdentityResource>
                {
                    new IdentityResources.OpenId(),
                    new IdentityResources.Profile(),
                    new IdentityResources.Email(),
                };
            }
    
            public static List<TestUser> GetTestUsers()
            {
                return new List<TestUser>
                {
                    new TestUser
                    {
                        SubjectId = "1",
                        Username = "mingsonzheng",
                        Password = "123456"
                    }
                };
            }
        }
    }
    

    startup 的 ConfigureServices

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddIdentityServer()
                .AddDeveloperSigningCredential()
                .AddInMemoryClients(Config.GetClients())
                .AddInMemoryApiResources(Config.GetApiResource())
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                .AddTestUsers(Config.GetTestUsers());
    
        //services.AddDbContext<ApplicationDbContext>(options =>
        //{
        //    options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
        //});
    
        //services.AddIdentity<ApplicationUser, ApplicationUserRole>()
        //    .AddEntityFrameworkStores<ApplicationDbContext>()
        //    .AddDefaultTokenProviders();
    
        //services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        //    .AddCookie(options => {
        //        options.LoginPath = "/Account/Login";
        //    });
    
        //services.Configure<IdentityOptions>(options =>
        //{
        //    options.Password.RequireLowercase = true;
        //    options.Password.RequireNonAlphanumeric = true;
        //    options.Password.RequireUppercase = true;
        //    options.Password.RequiredLength = 12;
        //});
    
        services.AddMvc();
    }
    

    startup 的 Configure 中 UseIdentityServer

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }
    
        app.UseStaticFiles();
        
        //app.UseAuthentication();
        app.UseIdentityServer();
    
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
    

    我们已经把 IdentityServer4 添加到 MVC 程序中,接着需要在 Controller 中实现这个逻辑

    首先注释 AccountController 原先的登录逻辑

    //private UserManager<ApplicationUser> _userManager;
    //private SignInManager<ApplicationUser> _signInManager;
    

    Logout 中使用 HttpContext.SignOutAsync 替换

    public async Task<IActionResult> Logout()
    {
        //await _signInManager.SignOutAsync();
        await HttpContext.SignOutAsync();
        return RedirectToAction("Index", "Home");
    }
    

    接着改造登录的逻辑,我们需要验证用户名和密码,前面我们在 Config 中添加了 TestUser,它被放在 TestUserStore 中,可以通过依赖注入引用进来,有了它之后就可以在登录的时候拿到用户名和密码

    private readonly TestUserStore _users;
    
    public AccountController(TestUserStore users)
    {
        _users = users;
    }
    

    因为 TestUser 本身不提供 Email 登录,所以我们需要修改 LoginViewModel 以及 Login.cshtml

    LoginViewModel

    [Required]
    //[DataType(DataType.EmailAddress)]
    //public string Email { get; set; }
    public string UserName { get; set; }
    

    Login.cshtml

    <div class="form-group">
        <label asp-for="UserName"></label>
        <input asp-for="UserName" class="form-control" />
        <span asp-validation-for="UserName" class="text-danger"></span>
    </div>
    

    改造登录的逻辑

    public async Task<IActionResult> Login(LoginViewModel loginViewModel,string returnUrl)
    {
        if (ModelState.IsValid)
        {
            //ViewData["ReturnUrl"] = returnUrl;
            //var user = await _userManager.FindByEmailAsync(loginViewModel.Email);
            //if (user == null)
            //{
            //    ModelState.AddModelError(nameof(loginViewModel.Email), "Email not exists");
            //}
            //else
            //{
            //    await _signInManager.SignInAsync(user, new AuthenticationProperties { IsPersistent = true });
            //    return RedirectToLoacl(returnUrl);
            //}
    
            ViewData["ReturnUrl"] = returnUrl;
            var user = _users.FindByUsername(loginViewModel.UserName);
            if (user == null)
            {
                ModelState.AddModelError(nameof(loginViewModel.UserName), "UserName not exists");
            }
            else
            {
                if (_users.ValidateCredentials(loginViewModel.UserName, loginViewModel.Password))
                {
                    var props = new AuthenticationProperties
                    {
                        IsPersistent = true,
                        ExpiresUtc = DateTimeOffset.UtcNow.Add(TimeSpan.FromMinutes(30)),
                    };
    
                    await Microsoft.AspNetCore.Http.AuthenticationManagerExtensions.SignInAsync(
                        HttpContext,
                        user.SubjectId,
                        user.Username,
                        props
                        );
    
                    return RedirectToLoacl(returnUrl);
                }
    
                ModelState.AddModelError(nameof(loginViewModel.Password), "Wrong Password");
            }
        }
    
        return View();
    }
    

    这样,我们就实现了一个通过 IdentityServer4 下的方法来实现了一个登录逻辑,然后做了一个跳转,下一节再把客户端加进来

    课程链接

    http://video.jessetalk.cn/course/explore

    知识共享许可协议

    本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

    欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。

    如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。

  • 相关阅读:
    HDU--2191 汶川地震购米(多重背包)
    PKU--1267 Cash Machine(多重背包)
    背包问题之多重背包
    NYOJ--311(完全背包)
    HDU--1114 Piggy-Bank(完全背包)
    MySQL的if,case语句
    测试一下MarkDown
    ThreadPoolExecutor介绍
    CountDownLatch的使用
    java中的信号量Semaphore
  • 原文地址:https://www.cnblogs.com/MingsonZheng/p/12861761.html
Copyright © 2011-2022 走看看