IdentityServer4[5]简化模式

Implicit简化模式(直接通过浏览器的链接跳转申请令牌)

简化模式是相对于授权码模式而言的。其不再需要【Client】的参与,所有的认证和授权都是通过浏览器来完成的。

创建项目
  • IdentityServer的ASP.NET Core Web空项目,端口5300

  • MvcClient的ASP.NET Core Web项目,端口5301

IdentityServer准备工作

定义API资源

public static IEnumerable<ApiResource> GetResources()
{
	return new List<ApiResource>()
	{
		new ApiResource("api","My Api")
	};
}
public static IEnumerable<IdentityResource> GetIdentityResource()
{
    return new List<IdentityResource>()
    {
        new IdentityResources.OpenId(),
        new IdentityResources.Profile(),
        new IdentityResources.Email()
    };
}

定义客户端

public static IEnumerable<Client> GetClients()
{
    return new List<Client>()
    {
        new Client()
        {
            ClientId="mvc",
            AllowedGrantTypes = GrantTypes.Implicit,
            ClientSecrets = new List<Secret>()
            {
                new Secret("secret".Sha256())
            },

            RequireConsent = false,

            RedirectUris = {"http://localhost:5301/signin-oidc"},
            PostLogoutRedirectUris = {"http://localhost:5301/signout-callback-oidc"},

            AllowedScopes =
            {
                IdentityServerConstants.StandardScopes.Profile,
                IdentityServerConstants.StandardScopes.OpenId
            }
        }
    };
}

定义测试用户

public static List<TestUser> GetUsers()
{
    return new List<TestUser>()
    {
        new TestUser()
        {
            SubjectId = "1",
            Username = "Test1",
            Password = "123456"
        }
    };
}

配置IdentityServer

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        services.AddIdentityServer()
            .AddDeveloperSigningCredential()
            .AddInMemoryClients(Config.GetClients())
            .AddInMemoryApiResources(Config.GetResources())
            .AddInMemoryIdentityResources(Config.GetIdentityResource())
            .AddTestUsers(Config.GetUsers());

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseStaticFiles();
        app.UseCookiePolicy();
        app.UseIdentityServer();
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

MvcClient准备

在Home控制器上,增加[Authorize]特性(授权)

[Authorize]
public class HomeController : Controller

Startup增加如下代码:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        services.AddIdentityServer()
            .AddDeveloperSigningCredential()
            .AddInMemoryClients(Config.GetClients())
            .AddInMemoryApiResources(Config.GetResources())
            .AddInMemoryIdentityResources(Config.GetIdentityResource())
            .AddTestUsers(Config.GetUsers());

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseStaticFiles();
        app.UseCookiePolicy();
        app.UseIdentityServer();
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

IdentityServer中Account控制器
public class AccountController : Controller
{
    private readonly TestUserStore _users;

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

    public IActionResult Login(string returnUrl = null)
    {
        ViewData["ReturnUrl"] = returnUrl;
        return View();
    }

    [HttpPost]
    public async Task<IActionResult> Login(LoginViewModel loginViewModel, string returnUrl = null)
    {
        if (ModelState.IsValid)
        {
            ViewData["ReturnUrl"] = returnUrl;
            var user = _users.FindByUsername(loginViewModel.UserName);
            if (user == null)
            {
                ModelState.AddModelError(nameof(loginViewModel.UserName), "UserName not exists");
            }

            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 Redirect(returnUrl);
            }
            else
            {
                ModelState.AddModelError(nameof(loginViewModel.Password), "password wrong");
            }
        }

        return View();
    }

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

定义Model

public class LoginViewModel
{
    [Required]
    public string UserName { get; set; }

    [Required]
    [DataType(DataType.Password)]
    public string Password { get; set; }

    [Display(Name = "Remember me?")]
    public bool RememberMe { get; set; }
}

前端代码

@model LoginViewModel
@{
    ViewData["Title"] = "Login";
}

<h2>Login</h2>

<div class="row">
    <div class="col-md-4">
        <section>
            <form method="post" asp-controller="Account" asp-action="Login" asp-route-returnUrl="@ViewData["ReturnUrl"]">
                <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="UserName"></label>
                    <input asp-for="UserName" class="form-control" />
                    <span asp-validation-for="UserName" 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">
                    <button type="submit" class="btn btn-default">Log in</button>
                </div>
            </form>
        </section>
    </div>
</div>


@section Scripts {
    @await Html.PartialAsync("_ValidationScriptsPartial")
}

先启动IdentityServer(5300),然后启动MvcClient(5301),会直接跳转到IdentityServer的登陆页,登陆后,会返回MvcClient的Home页。

IdentityServer4 中文文档与实战

IdentityServer4 知多少

jessetalk视频教程

posted @ 2020-07-31 09:00  蜗牛的希望  阅读(453)  评论(0编辑  收藏  举报