前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ASP.NET Core分布式项目实战(oauth2 + oidc 实现 server部分)--学习笔记

ASP.NET Core分布式项目实战(oauth2 + oidc 实现 server部分)--学习笔记

作者头像
郑子铭
发布2021-01-13 15:37:07
6690
发布2021-01-13 15:37:07
举报

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

基于之前快速入门的项目(MvcCookieAuthSample):

ASP.NET Core快速入门(第5章:认证与授权)--学习笔记

ASP.NET Core快速入门(第6章:ASP.NET Core MVC)--学习笔记

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

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

添加 identityserver4 引用

在 startup 中

代码语言:javascript
复制
using IdentityServer4;
按照之前的文章添加 Config.cs
代码语言:javascript
复制
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
代码语言:javascript
复制
// 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
代码语言:javascript
复制
// 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 原先的登录逻辑

代码语言:javascript
复制
//private UserManager<ApplicationUser> _userManager;
//private SignInManager<ApplicationUser> _signInManager;

Logout 中使用 HttpContext.SignOutAsync 替换

代码语言:javascript
复制
public async Task<IActionResult> Logout()
{
    //await _signInManager.SignOutAsync();
    await HttpContext.SignOutAsync();
    return RedirectToAction("Index", "Home");
}

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

代码语言:javascript
复制
private readonly TestUserStore _users;

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

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

LoginViewModel

代码语言:javascript
复制
[Required]
//[DataType(DataType.EmailAddress)]
//public string Email { get; set; }
public string UserName { get; set; }

Login.cshtml

代码语言:javascript
复制
<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>

改造登录的逻辑

代码语言:javascript
复制
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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-05-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DotNet NB 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 任务15:oauth2 + oidc 实现 server部分
    • 添加 identityserver4 引用
      • 按照之前的文章添加 Config.cs
        • startup 的 ConfigureServices
          • startup 的 Configure 中 UseIdentityServer
          • 课程链接
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档