Full Code of anjoy8/Blog.IdentityServer for AI

master 2ca932e9a30f cached
277 files
1.0 MB
271.9k tokens
330 symbols
1 requests
Download .txt
Showing preview only (1,169K chars total). Download the full file or copy to clipboard to get everything.
Repository: anjoy8/Blog.IdentityServer
Branch: master
Commit: 2ca932e9a30f
Files: 277
Total size: 1.0 MB

Directory structure:
gitextract_athlf9j7/

├── .dockerignore
├── .gitattributes
├── .gitignore
├── Blog.IdentityServer/
│   ├── Authorization/
│   │   ├── ClaimRequirement.cs
│   │   └── ClaimsRequirementHandler.cs
│   ├── Blog.IdentityServer.csproj
│   ├── Config.cs
│   ├── Controllers/
│   │   ├── Account/
│   │   │   ├── AccountController.cs
│   │   │   ├── AccountOptions.cs
│   │   │   ├── EditViewModel.cs
│   │   │   ├── ExternalController.cs
│   │   │   ├── ExternalProvider.cs
│   │   │   ├── ForgotPasswordViewModel.cs
│   │   │   ├── LoggedOutViewModel.cs
│   │   │   ├── LoginInputModel.cs
│   │   │   ├── LoginViewModel.cs
│   │   │   ├── LogoutInputModel.cs
│   │   │   ├── LogoutViewModel.cs
│   │   │   ├── RedirectViewModel.cs
│   │   │   ├── RegisterViewModel.cs
│   │   │   ├── ResetPasswordViewModel.cs
│   │   │   ├── RoleEditViewModel.cs
│   │   │   ├── RoleRegisterViewModel.cs
│   │   │   └── UrlHelperExtensions.cs
│   │   ├── ApiResource/
│   │   │   ├── ApiResourceDto.cs
│   │   │   └── ApiResourcesManager.cs
│   │   ├── Client/
│   │   │   ├── ClientDto.cs
│   │   │   └── ClientsManagerController.cs
│   │   ├── Consent/
│   │   │   ├── ConsentController.cs
│   │   │   ├── ConsentInputModel.cs
│   │   │   ├── ConsentOptions.cs
│   │   │   ├── ConsentViewModel.cs
│   │   │   ├── ProcessConsentResult.cs
│   │   │   └── ScopeViewModel.cs
│   │   ├── Device/
│   │   │   ├── DeviceAuthorizationInputModel.cs
│   │   │   ├── DeviceAuthorizationViewModel.cs
│   │   │   └── DeviceController.cs
│   │   ├── Diagnostics/
│   │   │   ├── DiagnosticsController.cs
│   │   │   └── DiagnosticsViewModel.cs
│   │   ├── Extensions.cs
│   │   ├── Grants/
│   │   │   ├── GrantsController.cs
│   │   │   └── GrantsViewModel.cs
│   │   ├── Home/
│   │   │   ├── ErrorViewModel.cs
│   │   │   ├── HomeController.cs
│   │   │   └── Is4ApiController.cs
│   │   ├── SecurityHeadersAttribute.cs
│   │   └── TestUsers.cs
│   ├── Data/
│   │   ├── ApplicationDbContext.cs
│   │   └── MigrationsMySql/
│   │       ├── 20200509165505_AppDbMigration.Designer.cs
│   │       ├── 20200509165505_AppDbMigration.cs
│   │       ├── 20210808045732_addQuestion.Designer.cs
│   │       ├── 20210808045732_addQuestion.cs
│   │       ├── ApplicationDbContextModelSnapshot.cs
│   │       └── IdentityServer/
│   │           ├── ConfigurationDb/
│   │           │   ├── 20200509165153_InitialIdentityServerConfigurationDbMigrationMysql.Designer.cs
│   │           │   ├── 20200509165153_InitialIdentityServerConfigurationDbMigrationMysql.cs
│   │           │   ├── 20200715033226_InitConfigurationDbV4.Designer.cs
│   │           │   ├── 20200715033226_InitConfigurationDbV4.cs
│   │           │   └── ConfigurationDbContextModelSnapshot.cs
│   │           └── PersistedGrantDb/
│   │               ├── 20200509165052_InitialIdentityServerPersistedGrantDbMigrationMysql.Designer.cs
│   │               ├── 20200509165052_InitialIdentityServerPersistedGrantDbMigrationMysql.cs
│   │               ├── 20200715032957_InitPersistedGrantDbV4.Designer.cs
│   │               ├── 20200715032957_InitPersistedGrantDbV4.cs
│   │               └── PersistedGrantDbContextModelSnapshot.cs
│   ├── Dockerfile
│   ├── Extensions/
│   │   ├── GrantTypeCustom.cs
│   │   ├── IpLimitMildd.cs
│   │   ├── IpPolicyRateLimitSetup.cs
│   │   ├── ResourceOwnerPasswordValidator.cs
│   │   └── WeiXinOpenGrantValidator.cs
│   ├── Helper/
│   │   ├── Appsettings.cs
│   │   ├── FileHelper.cs
│   │   ├── GetNetData.cs
│   │   ├── HtmlHelper.cs
│   │   ├── JsonHelper.cs
│   │   ├── MD5Hepler.cs
│   │   ├── RecursionHelper.cs
│   │   ├── SerializeHelper.cs
│   │   ├── UnicodeHelper.cs
│   │   └── UtilConvert.cs
│   ├── InMemoryConfig.cs
│   ├── LICENSE
│   ├── Models/
│   │   ├── ApplicationRole.cs
│   │   ├── ApplicationUser.cs
│   │   ├── ApplicationUserRole.cs
│   │   ├── Bak/
│   │   │   ├── Role.cs
│   │   │   ├── RootEntity.cs
│   │   │   ├── UserRole.cs
│   │   │   └── sysUserInfo.cs
│   │   ├── Dtos/
│   │   │   └── MessageModel.cs
│   │   └── ViewModel/
│   │       └── AccessApiDateView.cs
│   ├── Program.cs
│   ├── Properties/
│   │   ├── PublishProfiles/
│   │   │   └── FolderProfile.pubxml
│   │   └── launchSettings.json
│   ├── SameSiteHandlingExtensions.cs
│   ├── SeedData.cs
│   ├── Startup.cs
│   ├── Views/
│   │   ├── Account/
│   │   │   ├── AccessDenied.cshtml
│   │   │   ├── ConfirmEmail.cshtml
│   │   │   ├── Edit.cshtml
│   │   │   ├── ForgotPassword.cshtml
│   │   │   ├── ForgotPasswordConfirmation.cshtml
│   │   │   ├── LoggedOut.cshtml
│   │   │   ├── Login.cshtml
│   │   │   ├── Logout.cshtml
│   │   │   ├── My.cshtml
│   │   │   ├── Register.cshtml
│   │   │   ├── ResetPassword.cshtml
│   │   │   ├── ResetPasswordConfirmation.cshtml
│   │   │   ├── RoleEdit.cshtml
│   │   │   ├── RoleRegister.cshtml
│   │   │   ├── Roles.cshtml
│   │   │   └── Users.cshtml
│   │   ├── ApiResourcesManager/
│   │   │   ├── CreateOrEdit.cshtml
│   │   │   └── Index.cshtml
│   │   ├── ClientsManager/
│   │   │   ├── CreateOrEdit.cshtml
│   │   │   └── Index.cshtml
│   │   ├── Consent/
│   │   │   └── Index.cshtml
│   │   ├── Device/
│   │   │   ├── Success.cshtml
│   │   │   ├── UserCodeCapture.cshtml
│   │   │   └── UserCodeConfirmation.cshtml
│   │   ├── Diagnostics/
│   │   │   └── Index.cshtml
│   │   ├── Grants/
│   │   │   ├── Config.cshtml
│   │   │   └── Index.cshtml
│   │   ├── Home/
│   │   │   └── Index.cshtml
│   │   ├── Shared/
│   │   │   ├── Error.cshtml
│   │   │   ├── Redirect.cshtml
│   │   │   ├── _Layout.cshtml
│   │   │   ├── _ScopeListItem.cshtml
│   │   │   └── _ValidationSummary.cshtml
│   │   ├── _ViewImports.cshtml
│   │   └── _ViewStart.cshtml
│   ├── appsettings.Development.json
│   ├── appsettings.json
│   ├── tempkey.jwk
│   ├── tempkey.rsa
│   └── wwwroot/
│       ├── css/
│       │   ├── login_styles.css
│       │   ├── showtip.css
│       │   ├── site.css
│       │   ├── site.less
│       │   └── web.css
│       ├── fonts/
│       │   ├── FontAwesome.otf
│       │   └── open-iconic.otf
│       ├── js/
│       │   ├── Role.js
│       │   ├── User.js
│       │   ├── bootstrap-show-password.js
│       │   ├── showTip.js
│       │   ├── signin-redirect.js
│       │   └── signout-redirect.js
│       └── lib/
│           ├── bootstrap/
│           │   ├── css/
│           │   │   └── bootstrap.css
│           │   └── js/
│           │       └── bootstrap.js
│           ├── jquery-validation/
│           │   ├── .bower.json
│           │   ├── CONTRIBUTING.md
│           │   ├── Gruntfile.js
│           │   ├── LICENSE.md
│           │   ├── README.md
│           │   ├── bower.json
│           │   ├── changelog.md
│           │   ├── dist/
│           │   │   ├── additional-methods.js
│           │   │   └── jquery.validate.js
│           │   ├── package.json
│           │   ├── src/
│           │   │   ├── additional/
│           │   │   │   ├── accept.js
│           │   │   │   ├── additional.js
│           │   │   │   ├── alphanumeric.js
│           │   │   │   ├── bankaccountNL.js
│           │   │   │   ├── bankorgiroaccountNL.js
│           │   │   │   ├── bic.js
│           │   │   │   ├── cifES.js
│           │   │   │   ├── cpfBR.js
│           │   │   │   ├── creditcardtypes.js
│           │   │   │   ├── currency.js
│           │   │   │   ├── dateFA.js
│           │   │   │   ├── dateITA.js
│           │   │   │   ├── dateNL.js
│           │   │   │   ├── extension.js
│           │   │   │   ├── giroaccountNL.js
│           │   │   │   ├── iban.js
│           │   │   │   ├── integer.js
│           │   │   │   ├── ipv4.js
│           │   │   │   ├── ipv6.js
│           │   │   │   ├── lettersonly.js
│           │   │   │   ├── letterswithbasicpunc.js
│           │   │   │   ├── mobileNL.js
│           │   │   │   ├── mobileUK.js
│           │   │   │   ├── nieES.js
│           │   │   │   ├── nifES.js
│           │   │   │   ├── notEqualTo.js
│           │   │   │   ├── nowhitespace.js
│           │   │   │   ├── pattern.js
│           │   │   │   ├── phoneNL.js
│           │   │   │   ├── phoneUK.js
│           │   │   │   ├── phoneUS.js
│           │   │   │   ├── phonesUK.js
│           │   │   │   ├── postalCodeCA.js
│           │   │   │   ├── postalcodeBR.js
│           │   │   │   ├── postalcodeIT.js
│           │   │   │   ├── postalcodeNL.js
│           │   │   │   ├── postcodeUK.js
│           │   │   │   ├── require_from_group.js
│           │   │   │   ├── skip_or_fill_minimum.js
│           │   │   │   ├── statesUS.js
│           │   │   │   ├── strippedminlength.js
│           │   │   │   ├── time.js
│           │   │   │   ├── time12h.js
│           │   │   │   ├── url2.js
│           │   │   │   ├── vinUS.js
│           │   │   │   ├── zipcodeUS.js
│           │   │   │   └── ziprange.js
│           │   │   ├── ajax.js
│           │   │   ├── core.js
│           │   │   └── localization/
│           │   │       ├── messages_ar.js
│           │   │       ├── messages_bg.js
│           │   │       ├── messages_bn_BD.js
│           │   │       ├── messages_ca.js
│           │   │       ├── messages_cs.js
│           │   │       ├── messages_da.js
│           │   │       ├── messages_de.js
│           │   │       ├── messages_el.js
│           │   │       ├── messages_es.js
│           │   │       ├── messages_es_AR.js
│           │   │       ├── messages_es_PE.js
│           │   │       ├── messages_et.js
│           │   │       ├── messages_eu.js
│           │   │       ├── messages_fa.js
│           │   │       ├── messages_fi.js
│           │   │       ├── messages_fr.js
│           │   │       ├── messages_ge.js
│           │   │       ├── messages_gl.js
│           │   │       ├── messages_he.js
│           │   │       ├── messages_hr.js
│           │   │       ├── messages_hu.js
│           │   │       ├── messages_hy_AM.js
│           │   │       ├── messages_id.js
│           │   │       ├── messages_is.js
│           │   │       ├── messages_it.js
│           │   │       ├── messages_ja.js
│           │   │       ├── messages_ka.js
│           │   │       ├── messages_kk.js
│           │   │       ├── messages_ko.js
│           │   │       ├── messages_lt.js
│           │   │       ├── messages_lv.js
│           │   │       ├── messages_my.js
│           │   │       ├── messages_nl.js
│           │   │       ├── messages_no.js
│           │   │       ├── messages_pl.js
│           │   │       ├── messages_pt_BR.js
│           │   │       ├── messages_pt_PT.js
│           │   │       ├── messages_ro.js
│           │   │       ├── messages_ru.js
│           │   │       ├── messages_si.js
│           │   │       ├── messages_sk.js
│           │   │       ├── messages_sl.js
│           │   │       ├── messages_sr.js
│           │   │       ├── messages_sr_lat.js
│           │   │       ├── messages_sv.js
│           │   │       ├── messages_th.js
│           │   │       ├── messages_tj.js
│           │   │       ├── messages_tr.js
│           │   │       ├── messages_uk.js
│           │   │       ├── messages_vi.js
│           │   │       ├── messages_zh.js
│           │   │       ├── messages_zh_TW.js
│           │   │       ├── methods_de.js
│           │   │       ├── methods_es_CL.js
│           │   │       ├── methods_fi.js
│           │   │       ├── methods_nl.js
│           │   │       └── methods_pt.js
│           │   └── validation.jquery.json
│           └── jquery-validation-unobtrusive/
│               ├── .bower.json
│               ├── LICENSE.txt
│               ├── bower.json
│               └── jquery.validate.unobtrusive.js
├── Blog.IdentityServer.Publish.Docker.sh
├── Blog.IdentityServer.Publish.Linux.sh
├── Blog.IdentityServer.sln
├── Build.bat
├── Dockerfile
└── README.md

================================================
FILE CONTENTS
================================================

================================================
FILE: .dockerignore
================================================
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md

================================================
FILE: .gitattributes
================================================
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto

###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs     diff=csharp

###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following 
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln       merge=binary
#*.csproj    merge=binary
#*.vbproj    merge=binary
#*.vcxproj   merge=binary
#*.vcproj    merge=binary
#*.dbproj    merge=binary
#*.fsproj    merge=binary
#*.lsproj    merge=binary
#*.wixproj   merge=binary
#*.modelproj merge=binary
#*.sqlproj   merge=binary
#*.wwaproj   merge=binary

###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg   binary
#*.png   binary
#*.gif   binary

###############################################################################
# diff behavior for common document formats
# 
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the 
# entries below.
###############################################################################
#*.doc   diff=astextplain
#*.DOC   diff=astextplain
#*.docx  diff=astextplain
#*.DOCX  diff=astextplain
#*.dot   diff=astextplain
#*.DOT   diff=astextplain
#*.pdf   diff=astextplain
#*.PDF   diff=astextplain
#*.rtf   diff=astextplain
#*.RTF   diff=astextplain


================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.

# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/

# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUNIT
*.VisualState.xml
TestResult.xml

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# DNX
project.lock.json
project.fragment.lock.json
artifacts/

*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# Chutzpah Test files
_Chutzpah*

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb

# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap

# TFS 2012 Local Workspace
$tf/

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# JustCode is a .NET coding add-in
.JustCode

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/

# Web workbench (sass)
.sass-cache/

# Installshield output folder
[Ee]xpress/

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
#*.pubxml
*.publishproj

# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/

# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt

# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/

# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs

# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/

# RIA/Silverlight projects
Generated_Code/

# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm

# SQL Server files
*.mdf
*.ldf

# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings

# Microsoft Fakes
FakesAssemblies/

# GhostDoc plugin setting file
*.GhostDoc.xml

# Node.js Tools for Visual Studio
.ntvs_analysis.dat

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# Paket dependency manager
.paket/paket.exe
paket-files/

# FAKE - F# Make
.fake/

# JetBrains Rider
.idea/
*.sln.iml

# CodeRush
.cr/

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

*Logs/


================================================
FILE: Blog.IdentityServer/Authorization/ClaimRequirement.cs
================================================
using Microsoft.AspNetCore.Authorization;

namespace Blog.IdentityServer.Authorization
{
    public class ClaimRequirement : IAuthorizationRequirement
    {
        public ClaimRequirement(string claimName, string claimValue)
        {
            ClaimName = claimName;
            ClaimValue = claimValue;
        }

        public string ClaimName { get; set; }
        public string ClaimValue { get; set; }
    }
}

================================================
FILE: Blog.IdentityServer/Authorization/ClaimsRequirementHandler.cs
================================================
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;

namespace Blog.IdentityServer.Authorization
{
    public class ClaimsRequirementHandler : AuthorizationHandler<ClaimRequirement>
    {

        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                                       ClaimRequirement requirement)
        {

            var claim = context.User.Claims.FirstOrDefault(c => c.Type == requirement.ClaimName);
            if (claim != null && claim.Value.Contains(requirement.ClaimValue))
            {
                context.Succeed(requirement);
            }

            return Task.CompletedTask;
        }
    }
}

================================================
FILE: Blog.IdentityServer/Blog.IdentityServer.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <UserSecretsId>aspnet-IdentityServerWithAspNetIdentity-04C6939F-E672-4E56-B4A5-5F064EB67F23</UserSecretsId>
    <AssemblyName>Blog.IdentityServer</AssemblyName>
    <RootNamespace>Blog.IdentityServer</RootNamespace>
    <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
  </PropertyGroup>

  <ItemGroup>
    <Compile Remove="Data\Migrations\**" />
    <Compile Remove="Migrations\**" />
    <Compile Remove="Views\Oauth2\**" />
    <Content Remove="Data\Migrations\**" />
    <Content Remove="Migrations\**" />
    <Content Remove="Views\Oauth2\**" />
    <EmbeddedResource Remove="Data\Migrations\**" />
    <EmbeddedResource Remove="Migrations\**" />
    <EmbeddedResource Remove="Views\Oauth2\**" />
    <None Remove="Data\Migrations\**" />
    <None Remove="Migrations\**" />
    <None Remove="Views\Oauth2\**" />
  </ItemGroup>

  <ItemGroup>
    <Compile Remove="Controllers\Account\Oauth2Controller.cs" />
    <Compile Remove="Data\20191126135600_UpdateRoleTa.cs" />
    <Compile Remove="Data\20191126135600_UpdateRoleTa.Designer.cs" />
  </ItemGroup>


  <ItemGroup>
    <PackageReference Include="AspNetCoreRateLimit" Version="3.2.2" />
    <PackageReference Include="IdentityServer4" Version="4.0.2" />
    <PackageReference Include="IdentityServer4.AspNetIdentity" Version="4.0.2" />
    <PackageReference Include="IdentityServer4.EntityFramework" Version="4.0.2" />
    <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.8" />


    <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.5" />
    <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.5" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.5">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.5">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.1.5" />
    <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
    
    
    <PackageReference Include="Serilog.AspNetCore" Version="3.2.0" />
    <PackageReference Include="Serilog.Sinks.Console" Version="3.1.2-dev-00824" />
    <PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
    <PackageReference Include="System.Security.Principal.Windows" Version="4.7.0" />
  </ItemGroup>

  <ItemGroup>
    <DotNetCliToolReference Include="Microsoft.Extensions.SecretManager.Tools" Version="2.0.0" />
    <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />
  </ItemGroup>

  <ItemGroup>
    <None Include="wwwroot\Certificates\IS4.pfx" />
  </ItemGroup>

  <ItemGroup>
    <None Update="Dockerfile">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
  </ItemGroup>

  <ProjectExtensions><VisualStudio><UserProperties appsettings_1json__JsonSchema="" /></VisualStudio></ProjectExtensions>

</Project>


================================================
FILE: Blog.IdentityServer/Config.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.

using Blog.IdentityServer.Extensions;
using IdentityModel;
using IdentityServer4;
using IdentityServer4.Models;
using System.Collections.Generic;
using System.Linq;

namespace Blog.IdentityServer
{
    public class Config
    {
        // scopes define the resources in your system
        public static IEnumerable<IdentityResource> GetIdentityResources()
        {
            return new List<IdentityResource>
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),
                new IdentityResources.Email(),
                new IdentityResource("roles", "角色", new List<string> { JwtClaimTypes.Role }),
                new IdentityResource("rolename", "角色名", new List<string> { "rolename" }),
            };
        }

        // v4更新
        public static IEnumerable<ApiScope> GetApiScopes()
        {
            return new ApiScope[] {
                 new ApiScope("blog.core.api"),
                 new ApiScope("blog.core.api.BlogModule"),
            };
        }

        public static IEnumerable<ApiResource> GetApiResources()
        {
            // blog.core 项目
            return new List<ApiResource> {
                new ApiResource("blog.core.api", "Blog.Core API") {
                    // include the following using claims in access token (in addition to subject id)
                    //requires using using IdentityModel;
                    UserClaims = { JwtClaimTypes.Name, JwtClaimTypes.Role,"rolename" },
                    
                    // v4更新
                    Scopes={ "blog.core.api","blog.core.api.BlogModule"},

                    ApiSecrets = new List<Secret>()
                    {
                        new Secret("api_secret".Sha256())
                    },
                }
            };
        }

        // clients want to access resources (aka scopes)
        public static IEnumerable<Client> GetClients()
        {
            // client
            return new List<Client> {
                // 1、blog.vue 前端vue项目
                new Client {
                    ClientId = "blogvuejs",
                    ClientName = "Blog.Vue JavaScript Client",
                    AllowedGrantTypes = GrantTypes.Implicit,
                    AllowAccessTokensViaBrowser = true,

                    RedirectUris =           {
                        "http://vueblog.neters.club/callback",
                        "http://apk.neters.club/oauth2-redirect.html",

                        "http://localhost:6688/callback",
                        "http://localhost:8081/oauth2-redirect.html",
                    },
                    PostLogoutRedirectUris = { "http://vueblog.neters.club","http://localhost:6688" },
                    AllowedCorsOrigins =     { "http://vueblog.neters.club","http://localhost:6688" },

                    AccessTokenLifetime=3600,

                    AllowedScopes = {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        "roles",
                        "blog.core.api.BlogModule"
                    }
                },
                // 2、blog.admin 前端vue项目
                new Client {
                    ClientId = "blogadminjs",
                    ClientName = "Blog.Admin JavaScript Client",
                    AllowedGrantTypes = GrantTypes.Implicit,
                    AllowAccessTokensViaBrowser = true,

                    RedirectUris =
                    {
                        "http://vueadmin.neters.club/callback",
                        "http://apk.neters.club/oauth2-redirect.html",

                        "http://localhost:2364/callback",
                        "http://localhost:8081/oauth2-redirect.html",
                    },
                    PostLogoutRedirectUris = { "http://vueadmin.neters.club","http://localhost:2364" },
                    AllowedCorsOrigins =     { "http://vueadmin.neters.club","http://localhost:2364"  },

                    AccessTokenLifetime=3600,

                    AllowedScopes = {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        "roles",
                        "blog.core.api"
                    }
                },
                // 3、nuxt.tbug 前端nuxt项目
                new Client {
                    ClientId = "tibugnuxtjs",
                    ClientName = "Nuxt.tBug JavaScript Client",
                    AllowedGrantTypes = GrantTypes.Implicit,
                    AllowAccessTokensViaBrowser = true,

                    RedirectUris =           { "http://tibug.neters.club/callback" },
                    PostLogoutRedirectUris = { "http://tibug.neters.club" },
                    AllowedCorsOrigins =     { "http://tibug.neters.club" },

                    AccessTokenLifetime=3600,

                    AllowedScopes = {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        "roles",
                        "blog.core.api"
                    }
                },
                // 4、DDD 后端MVC项目
                new Client
                {
                    ClientId = "chrisdddmvc",
                    ClientSecrets = { new Secret("secret".Sha256()) },

                    AllowedGrantTypes = GrantTypes.Code,
                    RequireConsent = false,
                    RequirePkce = true,
                    AlwaysIncludeUserClaimsInIdToken=true,//将用户所有的claims包含在IdToken内
                
                    // where to redirect to after login
                    RedirectUris = { "http://ddd.neters.club/signin-oidc" },

                    // where to redirect to after logout
                    PostLogoutRedirectUris = { "http://ddd.neters.club/signout-callback-oidc" },

                    AllowedScopes = new List<string>
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        IdentityServerConstants.StandardScopes.Email,
                        "roles",
                        "rolename",
                    }
                },
                // 5、控制台客户端
                new Client
                {
                    ClientId = "Console",
                    ClientSecrets = { new Secret("secret".Sha256()) },

                     AllowOfflineAccess = true,//如果要获取refresh_tokens ,必须把AllowOfflineAccess设置为true
                    AllowedGrantTypes = new List<string>()
                    {
                        GrantTypes.ResourceOwnerPassword.FirstOrDefault(),
                        GrantTypes.ClientCredentials.FirstOrDefault(),
                        GrantTypeCustom.ResourceWeixinOpen,
                    },

                    AllowedScopes = new List<string>
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        "offline_access",
                        "blog.core.api"
                    }
                },
                // 6、mvp 后端blazor.server项目
                new Client
                {
                    ClientId = "blazorserver",
                    ClientSecrets = { new Secret("secret".Sha256()) },

                    AllowedGrantTypes = GrantTypes.Code,
                    RequireConsent = false,
                    RequirePkce = true,
                    AlwaysIncludeUserClaimsInIdToken=true,//将用户所有的claims包含在IdToken内
                    AllowAccessTokensViaBrowser = true,
                
                    // where to redirect to after login
                    RedirectUris = { "https://mvp.neters.club/signin-oidc" },

                    AllowedCorsOrigins =     { "https://mvp.neters.club" },
                   
                    // where to redirect to after logout
                    PostLogoutRedirectUris = { "https://mvp.neters.club/signout-callback-oidc" },

                    AllowedScopes = new List<string>
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        IdentityServerConstants.StandardScopes.Email,
                        "roles",
                        "rolename",
                        "blog.core.api"
                    }
                },

                // 7、测试 hybrid 模式
                new Client
                {
                    ClientId = "hybridclent",
                    ClientName="Demo MVC Client",
                    ClientSecrets = { new Secret("secret".Sha256()) },

                    AllowedGrantTypes = GrantTypes.Hybrid,
                 
                    RequirePkce = false,

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

                    AllowOfflineAccess=true,
                    AlwaysIncludeUserClaimsInIdToken=true,

                    AllowedScopes = new List<string>
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        IdentityServerConstants.StandardScopes.Email,
                        "roles",
                        "rolename",
                        "blog.core.api"
                    }
                }
            };
        }
    }
}

================================================
FILE: Blog.IdentityServer/Controllers/Account/AccountController.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


using IdentityServer4.Services;
using IdentityServer4.Stores;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using IdentityServer4.Events;
using IdentityServer4.Models;
using Microsoft.AspNetCore.Identity;
using IdentityServer4.Extensions;
using System.Security.Principal;
using System.Security.Claims;
using IdentityModel;
using System.Linq;
using System;
using System.Collections.Generic;
using Blog.IdentityServer.Models;
using Microsoft.AspNetCore.Authorization;
using Blog.Core.Common.Helper;

namespace IdentityServer4.Quickstart.UI
{
    [SecurityHeaders]
    public class AccountController : Controller
    {
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly RoleManager<ApplicationRole> _roleManager;
        private readonly SignInManager<ApplicationUser> _signInManager;
        private readonly IIdentityServerInteractionService _interaction;
        private readonly IClientStore _clientStore;
        private readonly IAuthenticationSchemeProvider _schemeProvider;
        private readonly IEventService _events;

        public AccountController(
            UserManager<ApplicationUser> userManager,
            RoleManager<ApplicationRole> roleManager,
            SignInManager<ApplicationUser> signInManager,
            IIdentityServerInteractionService interaction,
            IClientStore clientStore,
            IAuthenticationSchemeProvider schemeProvider,
            IEventService events)
        {
            _userManager = userManager;
            _roleManager = roleManager;
            _signInManager = signInManager;
            _interaction = interaction;
            _clientStore = clientStore;
            _schemeProvider = schemeProvider;
            _events = events;
        }

        /// <summary>
        /// Show login page
        /// </summary>
        [HttpGet]
        [Route("oauth2/authorize")]
        public async Task<IActionResult> Login(string returnUrl)
        {
            // build a model so we know what to show on the login page
            var vm = await BuildLoginViewModelAsync(returnUrl);

            if (vm.IsExternalLoginOnly)
            {
                // we only have one option for logging in and it's an external provider
                return await ExternalLogin(vm.ExternalLoginScheme, returnUrl);
            }

            return View(vm);
        }

        /// <summary>
        /// Handle postback from username/password login
        /// </summary>
        [HttpPost]
        [ValidateAntiForgeryToken]
        [Route("oauth2/authorize")]
        public async Task<IActionResult> Login(LoginInputModel model, string button)
        {
            // check if we are in the context of an authorization request
            var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl);

            if (button != "login")
            {
                if (context != null)
                {
                    // if the user cancels, send a result back into IdentityServer as if they 
                    // denied the consent (even if this client does not require consent).
                    // this will send back an access denied OIDC error response to the client.
                    await _interaction.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied);

                    // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
                    if (context.IsNativeClient())
                    {
                        // The client is native, so this change in how to
                        // return the response is for better UX for the end user.
                        return this.LoadingPage("Redirect", model.ReturnUrl);
                    }

                    return Redirect(model.ReturnUrl);
                }
                else
                {
                    // since we don't have a valid context, then we just go back to the home page
                    return Redirect("~/");
                }
            }

            if (ModelState.IsValid)
            {
                var user = _userManager.Users.FirstOrDefault(d => (d.LoginName == model.Username || d.Email == model.Username) && !d.tdIsDelete);

                if (user != null && !user.tdIsDelete)
                {
                    var result = await _signInManager.PasswordSignInAsync(user.LoginName, model.Password, model.RememberLogin, lockoutOnFailure: true);
                    if (result.Succeeded)
                    {
                        await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id.ToString(), user.UserName));

                        // make sure the returnUrl is still valid, and if so redirect back to authorize endpoint or a local page
                        // the IsLocalUrl check is only necessary if you want to support additional local pages, otherwise IsValidReturnUrl is more strict
                        if (_interaction.IsValidReturnUrl(model.ReturnUrl) || Url.IsLocalUrl(model.ReturnUrl))
                        {
                            return Redirect(model.ReturnUrl);
                        }

                        return Redirect("~/");
                    }
                    else
                    {
                        var result2 = await _signInManager.PasswordSignInAsync(user.UserName, model.Password, model.RememberLogin, lockoutOnFailure: true);

                        if (result2.Succeeded)
                        {
                            await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id.ToString(), user.UserName));

                            // make sure the returnUrl is still valid, and if so redirect back to authorize endpoint or a local page
                            // the IsLocalUrl check is only necessary if you want to support additional local pages, otherwise IsValidReturnUrl is more strict
                            if (_interaction.IsValidReturnUrl(model.ReturnUrl) || Url.IsLocalUrl(model.ReturnUrl))
                            {
                                return Redirect(model.ReturnUrl);
                            }

                            return Redirect("~/");
                        }
                    }
                }

                await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials"));

                ModelState.AddModelError("", AccountOptions.InvalidCredentialsErrorMessage);
            }

            // something went wrong, show form with error
            var vm = await BuildLoginViewModelAsync(model);
            return View(vm);
        }

        /// <summary>
        /// initiate roundtrip to external authentication provider
        /// </summary>
        [HttpGet]
        public async Task<IActionResult> ExternalLogin(string provider, string returnUrl)
        {
            if (AccountOptions.WindowsAuthenticationSchemeName == provider)
            {
                // windows authentication needs special handling
                return await ProcessWindowsLoginAsync(returnUrl);
            }
            else
            {
                // start challenge and roundtrip the return URL and 
                var props = new AuthenticationProperties()
                {
                    RedirectUri = Url.Action("ExternalLoginCallback"),
                    Items =
                    {
                        { "returnUrl", returnUrl },
                        { "scheme", provider },
                    }
                };
                return Challenge(props, provider);
            }
        }

        /// <summary>
        /// Post processing of external authentication
        /// </summary>
        [HttpGet]
        public async Task<IActionResult> ExternalLoginCallback()
        {
            // read external identity from the temporary cookie
            var result = await HttpContext.AuthenticateAsync(IdentityConstants.ExternalScheme);
            if (result?.Succeeded != true)
            {
                throw new Exception("External authentication error");
            }

            // lookup our user and external provider info
            var (user, provider, providerUserId, claims) = await FindUserFromExternalProviderAsync(result);
            if (user == null)
            {
                // this might be where you might initiate a custom workflow for user registration
                // in this sample we don't show how that would be done, as our sample implementation
                // simply auto-provisions new external user
                user = await AutoProvisionUserAsync(provider, providerUserId, claims);
            }

            // this allows us to collect any additonal claims or properties
            // for the specific prtotocols used and store them in the local auth cookie.
            // this is typically used to store data needed for signout from those protocols.
            var additionalLocalClaims = new List<Claim>();
            var localSignInProps = new AuthenticationProperties();
            ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps);
            ProcessLoginCallbackForWsFed(result, additionalLocalClaims, localSignInProps);
            ProcessLoginCallbackForSaml2p(result, additionalLocalClaims, localSignInProps);

            // issue authentication cookie for user
            // we must issue the cookie maually, and can't use the SignInManager because
            // it doesn't expose an API to issue additional claims from the login workflow
            var principal = await _signInManager.CreateUserPrincipalAsync(user);
            additionalLocalClaims.AddRange(principal.Claims);
            var name = principal.FindFirst(JwtClaimTypes.Name)?.Value ?? user.Id.ToString();
            await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.Id.ToString(), name));

            //await HttpContext.SignInAsync(user.Id.ToString(), name, provider, localSignInProps, additionalLocalClaims.ToArray());

            var isuser = new IdentityServerUser(user.Id.ToString())
            {
                DisplayName = name,
                IdentityProvider = provider,
                AdditionalClaims = additionalLocalClaims
            };

            await HttpContext.SignInAsync(isuser, localSignInProps);


            // delete temporary cookie used during external authentication
            await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);

            // validate return URL and redirect back to authorization endpoint or a local page
            var returnUrl = result.Properties.Items["returnUrl"];
            if (_interaction.IsValidReturnUrl(returnUrl) || Url.IsLocalUrl(returnUrl))
            {
                return Redirect(returnUrl);
            }

            return Redirect("~/");
        }

        /// <summary>
        /// Show logout page
        /// </summary>
        [HttpGet]
        public async Task<IActionResult> Logout(string logoutId)
        {
            // build a model so the logout page knows what to display
            var vm = await BuildLogoutViewModelAsync(logoutId);

            if (vm.ShowLogoutPrompt == false)
            {
                // if the request for logout was properly authenticated from IdentityServer, then
                // we don't need to show the prompt and can just log the user out directly.
                return await Logout(vm);
            }

            return View(vm);
        }

        /// <summary>
        /// Handle logout page postback
        /// </summary>
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Logout(LogoutInputModel model)
        {
            // build a model so the logged out page knows what to display
            var vm = await BuildLoggedOutViewModelAsync(model.LogoutId);

            if (User?.Identity.IsAuthenticated == true)
            {
                // delete local authentication cookie
                await _signInManager.SignOutAsync();

                // raise the logout event
                await _events.RaiseAsync(new UserLogoutSuccessEvent(User.GetSubjectId(), User.GetDisplayName()));
            }

            // check if we need to trigger sign-out at an upstream identity provider
            if (vm.TriggerExternalSignout)
            {
                // build a return URL so the upstream provider will redirect back
                // to us after the user has logged out. this allows us to then
                // complete our single sign-out processing.
                string url = Url.Action("Logout", new { logoutId = vm.LogoutId });

                // this triggers a redirect to the external provider for sign-out
                return SignOut(new AuthenticationProperties { RedirectUri = url }, vm.ExternalAuthenticationScheme);
            }

            return View("LoggedOut", vm);
        }

        /*****************************************/
        /* helper APIs for the AccountController */
        /*****************************************/
        private async Task<LoginViewModel> BuildLoginViewModelAsync(string returnUrl)
        {
            var context = await _interaction.GetAuthorizationContextAsync(returnUrl);
            if (context?.IdP != null)
            {
                // this is meant to short circuit the UI and only trigger the one external IdP
                return new LoginViewModel
                {
                    EnableLocalLogin = false,
                    ReturnUrl = returnUrl,
                    Username = context?.LoginHint,
                    ExternalProviders = new ExternalProvider[] { new ExternalProvider { AuthenticationScheme = context.IdP } }
                };
            }

            var schemes = await _schemeProvider.GetAllSchemesAsync();

            var providers = schemes
                .Where(x => x.DisplayName != null ||
                            (x.Name.Equals(AccountOptions.WindowsAuthenticationSchemeName, StringComparison.OrdinalIgnoreCase))
                )
                .Select(x => new ExternalProvider
                {
                    DisplayName = x.DisplayName,
                    AuthenticationScheme = x.Name
                }).ToList();

            var allowLocal = true;
            if (context?.Client.ClientId != null)
            {
                var client = await _clientStore.FindEnabledClientByIdAsync(context.Client.ClientId);
                if (client != null)
                {
                    allowLocal = client.EnableLocalLogin;

                    if (client.IdentityProviderRestrictions != null && client.IdentityProviderRestrictions.Any())
                    {
                        providers = providers.Where(provider => client.IdentityProviderRestrictions.Contains(provider.AuthenticationScheme)).ToList();
                    }
                }
            }

            return new LoginViewModel
            {
                AllowRememberLogin = AccountOptions.AllowRememberLogin,
                EnableLocalLogin = allowLocal && AccountOptions.AllowLocalLogin,
                ReturnUrl = returnUrl,
                Username = context?.LoginHint,
                ExternalProviders = providers.ToArray()
            };
        }

        private async Task<LoginViewModel> BuildLoginViewModelAsync(LoginInputModel model)
        {
            var vm = await BuildLoginViewModelAsync(model.ReturnUrl);
            vm.Username = model.Username;
            vm.RememberLogin = model.RememberLogin;
            return vm;
        }

        private async Task<LogoutViewModel> BuildLogoutViewModelAsync(string logoutId)
        {
            var vm = new LogoutViewModel { LogoutId = logoutId, ShowLogoutPrompt = AccountOptions.ShowLogoutPrompt };

            if (User?.Identity.IsAuthenticated != true)
            {
                // if the user is not authenticated, then just show logged out page
                vm.ShowLogoutPrompt = false;
                return vm;
            }

            var context = await _interaction.GetLogoutContextAsync(logoutId);
            if (context?.ShowSignoutPrompt == false)
            {
                // it's safe to automatically sign-out
                vm.ShowLogoutPrompt = false;
                return vm;
            }

            // show the logout prompt. this prevents attacks where the user
            // is automatically signed out by another malicious web page.
            return vm;
        }

        private async Task<LoggedOutViewModel> BuildLoggedOutViewModelAsync(string logoutId)
        {
            // get context information (client name, post logout redirect URI and iframe for federated signout)
            var logout = await _interaction.GetLogoutContextAsync(logoutId);

            var vm = new LoggedOutViewModel
            {
                AutomaticRedirectAfterSignOut = AccountOptions.AutomaticRedirectAfterSignOut,
                PostLogoutRedirectUri = logout?.PostLogoutRedirectUri,
                ClientName = string.IsNullOrEmpty(logout?.ClientName) ? logout?.ClientId : logout?.ClientName,
                SignOutIframeUrl = logout?.SignOutIFrameUrl,
                LogoutId = logoutId
            };

            if (User?.Identity.IsAuthenticated == true)
            {
                var idp = User.FindFirst(JwtClaimTypes.IdentityProvider)?.Value;
                if (idp != null && idp != IdentityServer4.IdentityServerConstants.LocalIdentityProvider)
                {
                    var providerSupportsSignout = await HttpContext.GetSchemeSupportsSignOutAsync(idp);
                    if (providerSupportsSignout)
                    {
                        if (vm.LogoutId == null)
                        {
                            // if there's no current logout context, we need to create one
                            // this captures necessary info from the current logged in user
                            // before we signout and redirect away to the external IdP for signout
                            vm.LogoutId = await _interaction.CreateLogoutContextAsync();
                        }

                        vm.ExternalAuthenticationScheme = idp;
                    }
                }
            }

            return vm;
        }

        private async Task<IActionResult> ProcessWindowsLoginAsync(string returnUrl)
        {
            // see if windows auth has already been requested and succeeded
            var result = await HttpContext.AuthenticateAsync(AccountOptions.WindowsAuthenticationSchemeName);
            if (result?.Principal is WindowsPrincipal wp)
            {
                // we will issue the external cookie and then redirect the
                // user back to the external callback, in essence, tresting windows
                // auth the same as any other external authentication mechanism
                var props = new AuthenticationProperties()
                {
                    RedirectUri = Url.Action("ExternalLoginCallback"),
                    Items =
                    {
                        { "returnUrl", returnUrl },
                        { "scheme", AccountOptions.WindowsAuthenticationSchemeName },
                    }
                };

                var id = new ClaimsIdentity(AccountOptions.WindowsAuthenticationSchemeName);
                id.AddClaim(new Claim(JwtClaimTypes.Subject, wp.Identity.Name));
                id.AddClaim(new Claim(JwtClaimTypes.Name, wp.Identity.Name));

                // add the groups as claims -- be careful if the number of groups is too large
                if (AccountOptions.IncludeWindowsGroups)
                {
                    var wi = wp.Identity as WindowsIdentity;
                    var groups = wi.Groups.Translate(typeof(NTAccount));
                    var roles = groups.Select(x => new Claim(JwtClaimTypes.Role, x.Value));
                    id.AddClaims(roles);
                }

                await HttpContext.SignInAsync(
                    IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme,
                    new ClaimsPrincipal(id),
                    props);
                return Redirect(props.RedirectUri);
            }
            else
            {
                // trigger windows auth
                // since windows auth don't support the redirect uri,
                // this URL is re-triggered when we call challenge
                return Challenge(AccountOptions.WindowsAuthenticationSchemeName);
            }
        }

        private async Task<(ApplicationUser user, string provider, string providerUserId, IEnumerable<Claim> claims)>
            FindUserFromExternalProviderAsync(AuthenticateResult result)
        {
            var externalUser = result.Principal;

            // try to determine the unique id of the external user (issued by the provider)
            // the most common claim type for that are the sub claim and the NameIdentifier
            // depending on the external provider, some other claim type might be used
            var userIdClaim = externalUser.FindFirst(JwtClaimTypes.Subject) ??
                              externalUser.FindFirst(ClaimTypes.NameIdentifier) ??
                              throw new Exception("Unknown userid");

            // remove the user id claim so we don't include it as an extra claim if/when we provision the user
            var claims = externalUser.Claims.ToList();
            claims.Remove(userIdClaim);

            var provider = result.Properties.Items["scheme"];
            var providerUserId = userIdClaim.Value;

            // find external user
            var user = await _userManager.FindByLoginAsync(provider, providerUserId);

            return (user, provider, providerUserId, claims);
        }

        private async Task<ApplicationUser> AutoProvisionUserAsync(string provider, string providerUserId, IEnumerable<Claim> claims)
        {
            // create a list of claims that we want to transfer into our store
            var filtered = new List<Claim>();

            // user's display name
            var name = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Name)?.Value ??
                claims.FirstOrDefault(x => x.Type == ClaimTypes.Name)?.Value;
            if (name != null)
            {
                filtered.Add(new Claim(JwtClaimTypes.Name, name));
            }
            else
            {
                var first = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.GivenName)?.Value ??
                    claims.FirstOrDefault(x => x.Type == ClaimTypes.GivenName)?.Value;
                var last = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.FamilyName)?.Value ??
                    claims.FirstOrDefault(x => x.Type == ClaimTypes.Surname)?.Value;
                if (first != null && last != null)
                {
                    filtered.Add(new Claim(JwtClaimTypes.Name, first + " " + last));
                }
                else if (first != null)
                {
                    filtered.Add(new Claim(JwtClaimTypes.Name, first));
                }
                else if (last != null)
                {
                    filtered.Add(new Claim(JwtClaimTypes.Name, last));
                }
            }

            // email
            var email = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Email)?.Value ??
               claims.FirstOrDefault(x => x.Type == ClaimTypes.Email)?.Value;
            if (email != null)
            {
                filtered.Add(new Claim(JwtClaimTypes.Email, email));
            }

            var user = new ApplicationUser
            {
                UserName = Guid.NewGuid().ToString(),
            };
            var identityResult = await _userManager.CreateAsync(user);
            if (!identityResult.Succeeded) throw new Exception(identityResult.Errors.First().Description);

            if (filtered.Any())
            {
                identityResult = await _userManager.AddClaimsAsync(user, filtered);
                if (!identityResult.Succeeded) throw new Exception(identityResult.Errors.First().Description);
            }

            identityResult = await _userManager.AddLoginAsync(user, new UserLoginInfo(provider, providerUserId, provider));
            if (!identityResult.Succeeded) throw new Exception(identityResult.Errors.First().Description);

            return user;
        }

        private void ProcessLoginCallbackForOidc(AuthenticateResult externalResult, List<Claim> localClaims, AuthenticationProperties localSignInProps)
        {
            // if the external system sent a session id claim, copy it over
            // so we can use it for single sign-out
            var sid = externalResult.Principal.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.SessionId);
            if (sid != null)
            {
                localClaims.Add(new Claim(JwtClaimTypes.SessionId, sid.Value));
            }

            // if the external provider issued an id_token, we'll keep it for signout
            var id_token = externalResult.Properties.GetTokenValue("id_token");
            if (id_token != null)
            {
                localSignInProps.StoreTokens(new[] { new AuthenticationToken { Name = "id_token", Value = id_token } });
            }
        }

        private void ProcessLoginCallbackForWsFed(AuthenticateResult externalResult, List<Claim> localClaims, AuthenticationProperties localSignInProps)
        {
        }

        private void ProcessLoginCallbackForSaml2p(AuthenticateResult externalResult, List<Claim> localClaims, AuthenticationProperties localSignInProps)
        {
        }




        [HttpGet]
        [Route("account/register")]
        public IActionResult Register(string returnUrl = null)
        {
            ViewData["ReturnUrl"] = returnUrl;
            return View();
        }

        [HttpPost]
        [Route("account/register")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null, string rName = "AdminTest")
        {
            ViewData["ReturnUrl"] = returnUrl;
            IdentityResult result = new IdentityResult();

            if (ModelState.IsValid)
            {
                var userItem = _userManager.FindByNameAsync(model.LoginName).Result;

                if (userItem == null)
                {

                    var user = new ApplicationUser
                    {
                        Email = model.Email,
                        UserName = model.LoginName,
                        LoginName = model.RealName,
                        sex = model.Sex,
                        age = model.Birth.Year - DateTime.Now.Year,
                        birth = model.Birth,
                        FirstQuestion = model.FirstQuestion,
                        SecondQuestion = model.SecondQuestion,
                        addr = "",
                        tdIsDelete = false
                    };


                    result = await _userManager.CreateAsync(user, model.Password);

                    if (result.Succeeded)
                    {
                        //var claims = new List<Claim>{
                        //            new Claim(JwtClaimTypes.Name, model.RealName),
                        //            new Claim(JwtClaimTypes.Email, model.Email),
                        //            new Claim(JwtClaimTypes.EmailVerified, "false", ClaimValueTypes.Boolean),
                        //            new Claim("rolename", rName),
                        //        };

                        //claims.AddRange((new List<int> { 6 }).Select(s => new Claim(JwtClaimTypes.Role, s.ToString())));


                        //result = _userManager.AddClaimsAsync(userItem, claims).Result;


                        result = await _userManager.AddClaimsAsync(user, new Claim[]{
                            new Claim(JwtClaimTypes.Name, model.RealName),
                            new Claim(JwtClaimTypes.Email, model.Email),
                            new Claim(JwtClaimTypes.EmailVerified, "false", ClaimValueTypes.Boolean),
                            new Claim(JwtClaimTypes.Role, "6"),
                            new Claim("rolename", rName),
                        });

                        if (result.Succeeded)
                        {
                            // 可以直接登录
                            //await _signInManager.SignInAsync(user, isPersistent: false);

                            return RedirectToLocal(returnUrl);
                        }
                    }

                }
                else
                {
                    ModelState.AddModelError(string.Empty, $"{userItem?.UserName} already exists");

                }

                AddErrors(result);
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }


        [HttpGet]
        [Route("account/users")]
        [Authorize]
        public IActionResult Users(string returnUrl = null)
        {
            ViewData["ReturnUrl"] = returnUrl;
            var users = _userManager.Users.Where(d => !d.tdIsDelete).OrderByDescending(d => d.Id).Take(50).ToList();

            return View(users);
        }



        [HttpGet("{id}")]
        [Route("account/edit/{id}")]
        [Authorize(Policy = "SuperAdmin")]
        public async Task<IActionResult> Edit(string id, string returnUrl = null)
        {
            ViewData["ReturnUrl"] = returnUrl;
            if (id == null)
            {
                return NotFound();
            }

            var user = await _userManager.FindByIdAsync(id);

            if (user == null)
            {
                return NotFound();
            }

            return View(new EditViewModel(user.Id.ToString(), user.LoginName, user.UserName, user.Email, await _userManager.GetClaimsAsync(user), user.FirstQuestion, user.SecondQuestion));
        }


        [HttpPost]
        [Route("account/edit/{id}")]
        [ValidateAntiForgeryToken]
        [Authorize(Policy = "SuperAdmin")]
        public async Task<IActionResult> Edit(EditViewModel model, string id, string returnUrl = null)
        {
            ViewData["ReturnUrl"] = returnUrl;
            IdentityResult result = new IdentityResult();

            if (ModelState.IsValid)
            {
                var userItem = _userManager.FindByIdAsync(model.Id).Result;

                if (userItem != null)
                {
                    var oldName = userItem.LoginName;
                    var oldEmail = userItem.Email;

                    userItem.UserName = model.LoginName;
                    userItem.LoginName = model.UserName;
                    userItem.Email = model.Email;
                    userItem.RealName = model.UserName;


                    result = await _userManager.UpdateAsync(userItem);

                    if (result.Succeeded)
                    {
                        var removeClaimsIdRst = await _userManager.RemoveClaimsAsync(userItem,
                            new Claim[]{
                                new Claim(JwtClaimTypes.Name, oldName),
                                new Claim(JwtClaimTypes.Email, oldEmail),
                        });

                        if (removeClaimsIdRst.Succeeded)
                        {
                            var addClaimsIdRst = await _userManager.AddClaimsAsync(userItem,
                                new Claim[]{
                                    new Claim(JwtClaimTypes.Name, userItem.LoginName),
                                    new Claim(JwtClaimTypes.Email, userItem.Email),
                            });

                            if (addClaimsIdRst.Succeeded)
                            {
                                return RedirectToLocal(returnUrl);
                            }
                            else
                            {
                                AddErrors(addClaimsIdRst);

                            }
                        }
                        else
                        {
                            AddErrors(removeClaimsIdRst);

                        }


                    }

                }
                else
                {
                    ModelState.AddModelError(string.Empty, $"{userItem?.UserName} no exist!");
                }

                AddErrors(result);
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }



        [HttpGet]
        [Route("account/my")]
        [Authorize]
        public async Task<IActionResult> My(string returnUrl = null)
        {
            ViewData["ReturnUrl"] = returnUrl;

            var id = (int.Parse)(HttpContext.User.Claims.FirstOrDefault(c => c.Type == "sub")?.Value);
            if (id <= 0)
            {
                return NotFound();
            }

            var user = await _userManager.FindByIdAsync(id.ToString());

            if (user == null)
            {
                return NotFound();
            }

            return View(new EditViewModel(user.Id.ToString(), user.LoginName, user.UserName, user.Email, await _userManager.GetClaimsAsync(user), user.FirstQuestion, user.SecondQuestion));
        }

        [HttpPost]
        [Route("account/my")]
        [ValidateAntiForgeryToken]
        [Authorize]
        public async Task<IActionResult> My(EditViewModel model, string returnUrl = null)
        {
            ViewData["ReturnUrl"] = returnUrl;
            IdentityResult result = new IdentityResult();

            if (ModelState.IsValid)
            {
                var id = (int.Parse)(HttpContext.User.Claims.FirstOrDefault(c => c.Type == "sub")?.Value);
                if (id <= 0)
                {
                    return NotFound();
                }

                // id为当前登录人
                if (model.Id == id.ToString())
                {
                    var userItem = _userManager.FindByIdAsync(model.Id).Result;
                    if (userItem != null)
                    {


                        var oldName = userItem.LoginName;
                        var oldEmail = userItem.Email;

                        userItem.UserName = model.LoginName;
                        userItem.LoginName = model.UserName;
                        userItem.Email = model.Email;
                        userItem.RealName = model.UserName;
                        userItem.FirstQuestion = model.FirstQuestion;
                        userItem.SecondQuestion = model.SecondQuestion;


                        result = await _userManager.UpdateAsync(userItem);

                        if (result.Succeeded)
                        {
                            var removeClaimsIdRst = await _userManager.RemoveClaimsAsync(userItem,
                                new Claim[]{
                                new Claim(JwtClaimTypes.Name, oldName),
                                new Claim(JwtClaimTypes.Email, oldEmail),
                            });

                            if (removeClaimsIdRst.Succeeded)
                            {
                                var addClaimsIdRst = await _userManager.AddClaimsAsync(userItem,
                                    new Claim[]{
                                    new Claim(JwtClaimTypes.Name, userItem.LoginName),
                                    new Claim(JwtClaimTypes.Email, userItem.Email),
                                });

                                if (addClaimsIdRst.Succeeded)
                                {
                                    return RedirectToLocal(returnUrl);
                                }
                                else
                                {
                                    AddErrors(addClaimsIdRst);

                                }
                            }
                            else
                            {
                                AddErrors(removeClaimsIdRst);

                            }


                        }


                    }
                    else
                    {
                        ModelState.AddModelError(string.Empty, $"{userItem?.UserName} no exist!");
                    }
                }
                else
                {
                    ModelState.AddModelError(string.Empty, $"您无权修改该数据!");
                }
                AddErrors(result);
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }


        [HttpPost]
        [Route("account/delete/{id}")]
        [Authorize(Policy = "SuperAdmin")]
        public async Task<JsonResult> Delete(string id)
        {
            IdentityResult result = new IdentityResult();

            if (ModelState.IsValid)
            {
                var userItem = _userManager.FindByIdAsync(id).Result;

                if (userItem != null)
                {
                    userItem.tdIsDelete = true;


                    result = await _userManager.UpdateAsync(userItem);

                    if (result.Succeeded)
                    {
                        return Json(result);
                    }

                }
                else
                {
                    ModelState.AddModelError(string.Empty, $"{userItem?.UserName} no exist!");
                }

                AddErrors(result);
            }

            return Json(result.Errors);

        }

        [HttpGet]
        [Route("account/confirm-email")]
        [AllowAnonymous]
        public async Task<IActionResult> ConfirmEmail(string userId, string code)
        {
            if (userId == null || code == null)
            {
                return RedirectToAction(nameof(HomeController.Index), "Home");
            }
            var user = await _userManager.FindByIdAsync(userId);
            if (user == null)
            {
                throw new ApplicationException($"Unable to load user with ID '{userId}'.");
            }
            var result = await _userManager.ConfirmEmailAsync(user, code);
            return View(result.Succeeded ? "ConfirmEmail" : "Error");
        }

        [HttpGet]
        [Route("account/forgot-password")]
        [AllowAnonymous]
        public IActionResult ForgotPassword()
        {
            return View();
        }

        [HttpPost]
        [Route("account/forgot-password")]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> ForgotPassword(ForgotPasswordViewModel model)
        {
            if (ModelState.IsValid)
            {
                var email = HttpContext.User.Claims.FirstOrDefault(c => c.Type == "email")?.Value;
                var roleName = HttpContext.User.Claims.FirstOrDefault(c => c.Type == "rolename")?.Value;
                if (email == model.Email || (roleName == "SuperAdmin"))
                {

                    var user = await _userManager.FindByEmailAsync(model.Email);
                    //if (user == null || !(await _userManager.IsEmailConfirmedAsync(user)))
                    if (user == null)
                    {
                        // Don't reveal that the user does not exist or is not confirmed
                        return RedirectToAction(nameof(ForgotPasswordConfirmation), new { ResetPassword = "邮箱不存在!" });
                    }

                    // For more information on how to enable account confirmation and password reset please
                    // visit https://go.microsoft.com/fwlink/?LinkID=532713
                    var code = await _userManager.GeneratePasswordResetTokenAsync(user);

                    var accessCode = MD5Helper.MD5Encrypt32(user.Id + code);
                    var callbackUrl = Url.ResetPasswordCallbackLink(user.Id.ToString(), code, Request.Scheme, accessCode);

                    var ResetPassword = $"Please reset your password by clicking here: <a href='{callbackUrl}'>link</a>";

                    return RedirectToAction(nameof(ForgotPasswordConfirmation), new { ResetPassword = ResetPassword });
                }
                else if (!string.IsNullOrEmpty(model.FirstQuestion) && !string.IsNullOrEmpty(model.SecondQuestion))
                {
                    var user = _userManager.Users.FirstOrDefault(d => d.Email == model.Email && d.FirstQuestion == model.FirstQuestion && d.SecondQuestion == model.SecondQuestion);
                    if (user == null)
                    {
                        return RedirectToAction(nameof(ForgotPasswordConfirmation), new { ResetPassword = "密保答案错误!" });
                    }

                    var code = await _userManager.GeneratePasswordResetTokenAsync(user);

                    var accessCode = MD5Helper.MD5Encrypt32(user.Id + code);
                    var callbackUrl = Url.ResetPasswordCallbackLink(user.Id.ToString(), code, Request.Scheme, accessCode);


                    var ResetPassword = $"Please reset your password by clicking here: <a href='{callbackUrl}'>link</a>";

                    return RedirectToAction(nameof(ForgotPasswordConfirmation), new { ResetPassword = ResetPassword });
                }
                else
                {
                    var forgetPwdUrl = "https://github.com/anjoy8/Blog.IdentityServer/issues";
                    return RedirectToAction(nameof(AccessDenied), new { errorMsg = $"只能在登录状态下或者输入正确密保的情况下,修改密码! <br>如果忘记密码,请联系超级管理员手动重置:<a href='{forgetPwdUrl}'>link</a>,提Issue" });
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        [HttpGet]
        [Route("account/forgot-password-confirmation")]
        [AllowAnonymous]
        public IActionResult ForgotPasswordConfirmation(string ResetPassword)
        {
            ViewBag.ResetPassword = ResetPassword;
            return View();
        }

        [HttpGet]
        [Route("account/reset-password")]
        [AllowAnonymous]
        public IActionResult ResetPassword(string code = null, string accessCode = null, string userId = "")
        {
            if (code == null || accessCode == null)
            {
                return RedirectToAction(nameof(AccessDenied), new { errorMsg = "code与accessCode必须都不能为空!" });
            }
            var model = new ResetPasswordViewModel { Code = code, AccessCode = accessCode, userId = userId };
            return View(model);
        }

        [HttpPost]
        [Route("account/reset-password")]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> ResetPassword(ResetPasswordViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return View(model);
            }

            var user = await _userManager.FindByEmailAsync(model.Email);
            if (user == null)
            {
                // Don't reveal that the user does not exist
                return RedirectToAction(nameof(ResetPasswordConfirmation));
            }


            // 防止篡改
            var getAccessCode = MD5Helper.MD5Encrypt32(model.userId + model.Code);
            if (getAccessCode != model.AccessCode)
            {
                return RedirectToAction(nameof(AccessDenied), new { errorMsg = "随机码已被篡改!密码重置失败!" });
            }

            if (user != null && user.Id.ToString() != model.userId)
            {
                return RedirectToAction(nameof(AccessDenied), new { errorMsg = "不能修改他人邮箱!密码重置失败!" });
            }


            var result = await _userManager.ResetPasswordAsync(user, model.Code, model.Password);
            if (result.Succeeded)
            {
                return RedirectToAction(nameof(ResetPasswordConfirmation));
            }
            AddErrors(result);
            return View();
        }

        [HttpGet]
        [Route("account/reset-password-confirmation")]
        [AllowAnonymous]
        public IActionResult ResetPasswordConfirmation()
        {
            return View();
        }


        [HttpGet]
        //[Route("account/access-denied")]
        public IActionResult AccessDenied(string errorMsg = "")
        {
            ViewBag.ErrorMsg = errorMsg;
            return View();
        }

        private void AddErrors(IdentityResult result)
        {
            foreach (var error in result.Errors)
            {
                ModelState.AddModelError(string.Empty, error.Description);
            }
        }

        private IActionResult RedirectToLocal(string returnUrl)
        {
            if (Url.IsLocalUrl(returnUrl))
            {
                return Redirect(returnUrl);
            }
            else
            {
                return RedirectToAction(nameof(HomeController.Index), "Home");
            }
        }


        // Role Manager



        [HttpGet]
        [Route("account/Roleregister")]
        public IActionResult RoleRegister(string returnUrl = null)
        {
            ViewData["ReturnUrl"] = returnUrl;
            return View();
        }

        [HttpPost]
        [Route("account/Roleregister")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> RoleRegister(RoleRegisterViewModel model, string returnUrl = null)
        {
            ViewData["ReturnUrl"] = returnUrl;
            IdentityResult result = new IdentityResult();

            if (ModelState.IsValid)
            {
                var roleItem = _roleManager.FindByNameAsync(model.RoleName).Result;

                if (roleItem == null)
                {

                    var role = new ApplicationRole
                    {
                        Name = model.RoleName
                    };


                    result = await _roleManager.CreateAsync(role);

                    if (result.Succeeded)
                    {

                        if (result.Succeeded)
                        {
                            // 可以直接登录
                            //await _signInManager.SignInAsync(user, isPersistent: false);

                            return RedirectToLocal(returnUrl);
                        }
                    }

                }
                else
                {
                    ModelState.AddModelError(string.Empty, $"{roleItem?.Name} already exists");

                }

                AddErrors(result);
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }


        [HttpGet]
        [Route("account/Roles")]
        [Authorize]
        public IActionResult Roles(string returnUrl = null)
        {
            ViewData["ReturnUrl"] = returnUrl;
            var roles = _roleManager.Roles.Where(d => !d.IsDeleted).ToList();

            return View(roles);
        }



        [HttpGet("{id}")]
        [Route("account/Roleedit/{id}")]
        [Authorize(Policy = "SuperAdmin")]
        public async Task<IActionResult> RoleEdit(string id, string returnUrl = null)
        {
            ViewData["ReturnUrl"] = returnUrl;
            if (id == null)
            {
                return NotFound();
            }

            var user = await _roleManager.FindByIdAsync(id);

            if (user == null)
            {
                return NotFound();
            }

            return View(new RoleEditViewModel(user.Id.ToString(), user.Name));
        }


        [HttpPost]
        [Route("account/Roleedit/{id}")]
        [ValidateAntiForgeryToken]
        [Authorize(Policy = "SuperAdmin")]
        public async Task<IActionResult> RoleEdit(RoleEditViewModel model, string id, string returnUrl = null)
        {
            ViewData["ReturnUrl"] = returnUrl;
            IdentityResult result = new IdentityResult();

            if (ModelState.IsValid)
            {
                var roleItem = _roleManager.FindByIdAsync(model.Id).Result;

                if (roleItem != null)
                {
                    roleItem.Name = model.RoleName;


                    result = await _roleManager.UpdateAsync(roleItem);

                    if (result.Succeeded)
                    {
                        return RedirectToLocal(returnUrl);
                    }

                }
                else
                {
                    ModelState.AddModelError(string.Empty, $"{roleItem?.Name} no exist!");
                }

                AddErrors(result);
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }



        [HttpPost]
        [Route("account/Roledelete/{id}")]
        [Authorize(Policy = "SuperAdmin")]
        public async Task<JsonResult> RoleDelete(string id)
        {
            IdentityResult result = new IdentityResult();

            if (ModelState.IsValid)
            {
                var roleItem = _roleManager.FindByIdAsync(id).Result;

                if (roleItem != null)
                {
                    roleItem.IsDeleted = true;


                    result = await _roleManager.UpdateAsync(roleItem);

                    if (result.Succeeded)
                    {
                        return Json(result);
                    }

                }
                else
                {
                    ModelState.AddModelError(string.Empty, $"{roleItem?.Name} no exist!");
                }

                AddErrors(result);
            }

            return Json(result.Errors);

        }
    }
}


================================================
FILE: Blog.IdentityServer/Controllers/Account/AccountOptions.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


using System;

namespace IdentityServer4.Quickstart.UI
{
    public class AccountOptions
    {
        public static bool AllowLocalLogin = true;
        public static bool AllowRememberLogin = true;
        public static TimeSpan RememberMeLoginDuration = TimeSpan.FromDays(30);

        public static bool ShowLogoutPrompt = true;
        public static bool AutomaticRedirectAfterSignOut = true;//自动跳回原项目

        // specify the Windows authentication scheme being used
        public static readonly string WindowsAuthenticationSchemeName = Microsoft.AspNetCore.Server.IISIntegration.IISDefaults.AuthenticationScheme;
        // if user uses windows auth, should we load the groups from windows
        public static bool IncludeWindowsGroups = false;

        public static string InvalidCredentialsErrorMessage = "Invalid username or password";
    }
}


================================================
FILE: Blog.IdentityServer/Controllers/Account/EditViewModel.cs
================================================
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Security.Claims;

namespace IdentityServer4.Quickstart.UI
{
    public class EditViewModel
    {
        public EditViewModel()
        {

        }
        public EditViewModel(string Id, string Name, string LoginName, string Email, IList<Claim> Claims, string FirstQuestion, string SecondQuestion)
        {
            this.Id = Id;
            this.LoginName = LoginName;
            this.Email = Email;
            this.UserName = Name;
            this.Claims = Claims;
            this.FirstQuestion = FirstQuestion;
            this.SecondQuestion = SecondQuestion;
        }

        public string Id { get; set; }

        [Required]
        [Display(Name = "昵称")]
        public string UserName { get; set; }

        [Required]
        [Display(Name = "登录名")]
        public string LoginName { get; set; }

        [Required]
        [EmailAddress]
        [Display(Name = "邮箱")]
        public string Email { get; set; }




        [Display(Name = "性别")]
        public int Sex { get; set; } = 0;

        [Display(Name = "生日")]
        public DateTime Birth { get; set; } = DateTime.Now;

        public IList<Claim> Claims { get; set; }


        [Display(Name = "密保问题一:你喜欢的动漫?")]
        public string FirstQuestion { get; set; }

        [Display(Name = "密保问题二:你喜欢的名著?")]
        public string SecondQuestion { get; set; }
    }
}


================================================
FILE: Blog.IdentityServer/Controllers/Account/ExternalController.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Blog.IdentityServer.Models;
using IdentityModel;
using IdentityServer4;
using IdentityServer4.Events;
using IdentityServer4.Models;
using IdentityServer4.Services;
using IdentityServer4.Stores;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace IdentityServer4.Quickstart.UI
{
    [SecurityHeaders]
    [AllowAnonymous]
    public class ExternalController : Controller
    {
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly SignInManager<ApplicationUser> _signInManager;
        private readonly IIdentityServerInteractionService _interaction;
        private readonly IClientStore _clientStore;
        private readonly IEventService _events;
        private readonly ILogger<ExternalController> _logger;

        public ExternalController(
            UserManager<ApplicationUser> userManager,
            SignInManager<ApplicationUser> signInManager,
            IIdentityServerInteractionService interaction,
            IClientStore clientStore,
            IEventService events,
            ILogger<ExternalController> logger)
        {
            _userManager = userManager;
            _signInManager = signInManager;
            _interaction = interaction;
            _clientStore = clientStore;
            _events = events;
            _logger = logger;
        }

        /// <summary>
        /// initiate roundtrip to external authentication provider
        /// </summary>
        [HttpGet]
        public IActionResult Challenge(string scheme, string returnUrl)
        {
            if (string.IsNullOrEmpty(returnUrl)) returnUrl = "~/";

            // validate returnUrl - either it is a valid OIDC URL or back to a local page
            if (Url.IsLocalUrl(returnUrl) == false && _interaction.IsValidReturnUrl(returnUrl) == false)
            {
                // user might have clicked on a malicious link - should be logged
                throw new Exception("invalid return URL");
            }

            // start challenge and roundtrip the return URL and scheme 
            var props = new AuthenticationProperties
            {
                RedirectUri = Url.Action(nameof(Callback)),
                Items =
                {
                    { "returnUrl", returnUrl },
                    { "scheme", scheme },
                }
            };

            return Challenge(props, scheme);

        }

        /// <summary>
        /// Post processing of external authentication
        /// </summary>
        [HttpGet]
        public async Task<IActionResult> Callback()
        {
            // read external identity from the temporary cookie
            var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);
            if (result?.Succeeded != true)
            {
                throw new Exception("External authentication error");
            }

            if (_logger.IsEnabled(LogLevel.Debug))
            {
                var externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}");
                _logger.LogDebug("External claims: {@claims}", externalClaims);
            }

            // lookup our user and external provider info
            var (user, provider, providerUserId, claims) = await FindUserFromExternalProviderAsync(result);
            if (user == null)
            {
                // this might be where you might initiate a custom workflow for user registration
                // in this sample we don't show how that would be done, as our sample implementation
                // simply auto-provisions new external user
                user = await AutoProvisionUserAsync(provider, providerUserId, claims);
            }

            // this allows us to collect any additional claims or properties
            // for the specific protocols used and store them in the local auth cookie.
            // this is typically used to store data needed for signout from those protocols.
            var additionalLocalClaims = new List<Claim>();
            var localSignInProps = new AuthenticationProperties();
            ProcessLoginCallback(result, additionalLocalClaims, localSignInProps);

            // issue authentication cookie for user
            // we must issue the cookie maually, and can't use the SignInManager because
            // it doesn't expose an API to issue additional claims from the login workflow
            var principal = await _signInManager.CreateUserPrincipalAsync(user);
            additionalLocalClaims.AddRange(principal.Claims);
            var name = principal.FindFirst(JwtClaimTypes.Name)?.Value ?? user.Id.ToString();

            var isuser = new IdentityServerUser(user.Id.ToString())
            {
                DisplayName = name,
                IdentityProvider = provider,
                AdditionalClaims = additionalLocalClaims
            };

            await HttpContext.SignInAsync(isuser, localSignInProps);

            // delete temporary cookie used during external authentication
            await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);

            // retrieve return URL
            var returnUrl = result.Properties.Items["returnUrl"] ?? "~/";

            // check if external login is in the context of an OIDC request
            var context = await _interaction.GetAuthorizationContextAsync(returnUrl);
            await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.Id.ToString(), name, true, context?.Client.ClientId));

            if (context != null)
            {
                if (context.IsNativeClient())
                {
                    // The client is native, so this change in how to
                    // return the response is for better UX for the end user.
                    return this.LoadingPage("Redirect", returnUrl);
                }
            }

            return Redirect(returnUrl);
        }

        private async Task<(ApplicationUser user, string provider, string providerUserId, IEnumerable<Claim> claims)>
            FindUserFromExternalProviderAsync(AuthenticateResult result)
        {
            var externalUser = result.Principal;

            // try to determine the unique id of the external user (issued by the provider)
            // the most common claim type for that are the sub claim and the NameIdentifier
            // depending on the external provider, some other claim type might be used
            var userIdClaim = externalUser.FindFirst(JwtClaimTypes.Subject) ??
                              externalUser.FindFirst(ClaimTypes.NameIdentifier) ??
                              throw new Exception("Unknown userid");

            // remove the user id claim so we don't include it as an extra claim if/when we provision the user
            var claims = externalUser.Claims.ToList();
            claims.Remove(userIdClaim);

            var provider = result.Properties.Items["scheme"];
            var providerUserId = userIdClaim.Value;

            // find external user
            var user = await _userManager.FindByLoginAsync(provider, providerUserId);

            return (user, provider, providerUserId, claims);
        }

        private async Task<ApplicationUser> AutoProvisionUserAsync(string provider, string providerUserId, IEnumerable<Claim> claims)
        {
            // create a list of claims that we want to transfer into our store
            var filtered = new List<Claim>();

            // user's display name
            var name = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Name)?.Value ??
                claims.FirstOrDefault(x => x.Type == ClaimTypes.Name)?.Value;
            if (name != null)
            {
                filtered.Add(new Claim(JwtClaimTypes.Name, name));
            }
            else
            {
                var first = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.GivenName)?.Value ??
                    claims.FirstOrDefault(x => x.Type == ClaimTypes.GivenName)?.Value;
                var last = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.FamilyName)?.Value ??
                    claims.FirstOrDefault(x => x.Type == ClaimTypes.Surname)?.Value;
                if (first != null && last != null)
                {
                    filtered.Add(new Claim(JwtClaimTypes.Name, first + " " + last));
                }
                else if (first != null)
                {
                    filtered.Add(new Claim(JwtClaimTypes.Name, first));
                }
                else if (last != null)
                {
                    filtered.Add(new Claim(JwtClaimTypes.Name, last));
                }
            }

            // email
            var email = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Email)?.Value ??
               claims.FirstOrDefault(x => x.Type == ClaimTypes.Email)?.Value;
            if (email != null)
            {
                filtered.Add(new Claim(JwtClaimTypes.Email, email));
            }

            var user = new ApplicationUser
            {
                UserName = Guid.NewGuid().ToString(),
            };
            var identityResult = await _userManager.CreateAsync(user);
            if (!identityResult.Succeeded) throw new Exception(identityResult.Errors.First().Description);

            if (filtered.Any())
            {
                identityResult = await _userManager.AddClaimsAsync(user, filtered);
                if (!identityResult.Succeeded) throw new Exception(identityResult.Errors.First().Description);
            }

            identityResult = await _userManager.AddLoginAsync(user, new UserLoginInfo(provider, providerUserId, provider));
            if (!identityResult.Succeeded) throw new Exception(identityResult.Errors.First().Description);

            return user;
        }

        // if the external login is OIDC-based, there are certain things we need to preserve to make logout work
        // this will be different for WS-Fed, SAML2p or other protocols
        private void ProcessLoginCallback(AuthenticateResult externalResult, List<Claim> localClaims, AuthenticationProperties localSignInProps)
        {
            // if the external system sent a session id claim, copy it over
            // so we can use it for single sign-out
            var sid = externalResult.Principal.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.SessionId);
            if (sid != null)
            {
                localClaims.Add(new Claim(JwtClaimTypes.SessionId, sid.Value));
            }

            // if the external provider issued an id_token, we'll keep it for signout
            var idToken = externalResult.Properties.GetTokenValue("id_token");
            if (idToken != null)
            {
                localSignInProps.StoreTokens(new[] { new AuthenticationToken { Name = "id_token", Value = idToken } });
            }
        }
    }
}

================================================
FILE: Blog.IdentityServer/Controllers/Account/ExternalProvider.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


namespace IdentityServer4.Quickstart.UI
{
    public class ExternalProvider
    {
        public string DisplayName { get; set; }
        public string AuthenticationScheme { get; set; }
    }
}

================================================
FILE: Blog.IdentityServer/Controllers/Account/ForgotPasswordViewModel.cs
================================================
using System.ComponentModel.DataAnnotations;

namespace IdentityServer4.Quickstart.UI
{
    public class ForgotPasswordViewModel
    {
        [Required]
        [EmailAddress]
        public string Email { get; set; }

        [Display(Name = "密保问题一:你喜欢的动漫?")]
        public string FirstQuestion { get; set; }

        [Display(Name = "密保问题二:你喜欢的名著?")]
        public string SecondQuestion { get; set; }
    }
}


================================================
FILE: Blog.IdentityServer/Controllers/Account/LoggedOutViewModel.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


namespace IdentityServer4.Quickstart.UI
{
    public class LoggedOutViewModel
    {
        public string PostLogoutRedirectUri { get; set; }
        public string ClientName { get; set; }
        public string SignOutIframeUrl { get; set; }

        public bool AutomaticRedirectAfterSignOut { get; set; } = false;

        public string LogoutId { get; set; }
        public bool TriggerExternalSignout => ExternalAuthenticationScheme != null;
        public string ExternalAuthenticationScheme { get; set; }
    }
}

================================================
FILE: Blog.IdentityServer/Controllers/Account/LoginInputModel.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


using System.ComponentModel.DataAnnotations;

namespace IdentityServer4.Quickstart.UI
{
    public class LoginInputModel
    {
        [Required]
        public string Username { get; set; }
        [Required]
        public string Password { get; set; }
        public bool RememberLogin { get; set; }
        public string ReturnUrl { get; set; }
    }
}

================================================
FILE: Blog.IdentityServer/Controllers/Account/LoginViewModel.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


using System;
using System.Collections.Generic;
using System.Linq;

namespace IdentityServer4.Quickstart.UI
{
    public class LoginViewModel : LoginInputModel
    {
        public bool AllowRememberLogin { get; set; } = true;
        public bool EnableLocalLogin { get; set; } = true;

        public IEnumerable<ExternalProvider> ExternalProviders { get; set; } = Enumerable.Empty<ExternalProvider>();
        public IEnumerable<ExternalProvider> VisibleExternalProviders => ExternalProviders.Where(x => !String.IsNullOrWhiteSpace(x.DisplayName));

        public bool IsExternalLoginOnly => EnableLocalLogin == false && ExternalProviders?.Count() == 1;
        public string ExternalLoginScheme => IsExternalLoginOnly ? ExternalProviders?.SingleOrDefault()?.AuthenticationScheme : null;
    }
}

================================================
FILE: Blog.IdentityServer/Controllers/Account/LogoutInputModel.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


namespace IdentityServer4.Quickstart.UI
{
    public class LogoutInputModel
    {
        public string LogoutId { get; set; }
    }
}


================================================
FILE: Blog.IdentityServer/Controllers/Account/LogoutViewModel.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


namespace IdentityServer4.Quickstart.UI
{
    public class LogoutViewModel : LogoutInputModel
    {
        public bool ShowLogoutPrompt { get; set; } = true;
    }
}


================================================
FILE: Blog.IdentityServer/Controllers/Account/RedirectViewModel.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.



namespace IdentityServer4.Quickstart.UI
{
    public class RedirectViewModel
    {
        public string RedirectUrl { get; set; }
    }
}

================================================
FILE: Blog.IdentityServer/Controllers/Account/RegisterViewModel.cs
================================================
using System;
using System.ComponentModel.DataAnnotations;

namespace IdentityServer4.Quickstart.UI
{
    public class RegisterViewModel
    {

        [Required]
        [Display(Name = "昵称")]
        public string RealName { get; set; }

        [Required]
        [Display(Name = "登录名")]
        public string LoginName { get; set; }

        [Required]
        [EmailAddress]
        [Display(Name = "邮箱")]
        public string Email { get; set; }

        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "密码")]
        public string Password { get; set; }

        [DataType(DataType.Password)]
        [Display(Name = "确认密码")]
        [Compare("Password", ErrorMessage = "The 密码 and 确认密码 do not match.")]
        public string ConfirmPassword { get; set; }



        [Required]
        [Display(Name = "密保问题一:你喜欢的动漫?")]
        public string FirstQuestion { get; set; }

        [Required]
        [Display(Name = "密保问题二:你喜欢的名著?")]
        public string SecondQuestion { get; set; }

        [Display(Name = "性别")]
        public int Sex { get; set; } = 0;

        [Display(Name = "生日")]
        public DateTime Birth { get; set; } = DateTime.Now;
    }
}


================================================
FILE: Blog.IdentityServer/Controllers/Account/ResetPasswordViewModel.cs
================================================
using System.ComponentModel.DataAnnotations;

namespace IdentityServer4.Quickstart.UI
{
    public class ResetPasswordViewModel
    {
        [Required]
        public string userId { get; set; }

        [Required]
        [EmailAddress]
        public string Email { get; set; }

        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
        [DataType(DataType.Password)]
        public string Password { get; set; }

        [DataType(DataType.Password)]
        [Display(Name = "Confirm password")]
        [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
        public string ConfirmPassword { get; set; }

        public string Code { get; set; }
        public string AccessCode { get; set; }
    }
}


================================================
FILE: Blog.IdentityServer/Controllers/Account/RoleEditViewModel.cs
================================================
using System;
using System.ComponentModel.DataAnnotations;

namespace IdentityServer4.Quickstart.UI
{
    public class RoleEditViewModel
    {
        public RoleEditViewModel()
        {
           
        }
        public RoleEditViewModel(string Id, string Name)
        {
            this.Id = Id;
            this.RoleName = Name;
        }

        public string Id { get; set; }

        [Required]
        [Display(Name = "角色名")]
        public string RoleName { get; set; }

       
    }
}


================================================
FILE: Blog.IdentityServer/Controllers/Account/RoleRegisterViewModel.cs
================================================
using System;
using System.ComponentModel.DataAnnotations;

namespace IdentityServer4.Quickstart.UI
{
    public class RoleRegisterViewModel
    {

        [Required]
        [Display(Name = "角色名")]
        public string RoleName { get; set; }

        
    }
}


================================================
FILE: Blog.IdentityServer/Controllers/Account/UrlHelperExtensions.cs
================================================
using Microsoft.AspNetCore.Mvc;

namespace IdentityServer4.Quickstart.UI
{
    public static class UrlHelperExtensions
    {
        public static string EmailConfirmationLink(this IUrlHelper urlHelper, string userId, string code, string scheme)
        {
            return urlHelper.Action(
                action: nameof(AccountController.ConfirmEmail),
                controller: "Account",
                values: new { userId, code },
                protocol: scheme);
        }

        public static string ResetPasswordCallbackLink(this IUrlHelper urlHelper, string userId, string code, string scheme, string accessCode = "")
        {
            return urlHelper.Action(
                action: nameof(AccountController.ResetPassword),
                controller: "Account",
                values: new { userId, code, accessCode },
                protocol: scheme);
        }
    }
}


================================================
FILE: Blog.IdentityServer/Controllers/ApiResource/ApiResourceDto.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Blog.IdentityServer.Controllers.ApiResource
{
    public class ApiResourceDto
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string DisplayName { get; set; }
        public string Description { get; set; }
        public string UserClaims { get; set; }
        public string Scopes { get; set; }
    }
}


================================================
FILE: Blog.IdentityServer/Controllers/ApiResource/ApiResourcesManager.cs
================================================
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Blog.IdentityServer.Models;
using IdentityServer4.EntityFramework.DbContexts;
using IdentityServer4.EntityFramework.Mappers;
using IdentityServer4.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace Blog.IdentityServer.Controllers.ApiResource
{
    [Route("[controller]/[action]")]
    [ApiController]
    public class ApiResourcesManager : Controller
    {
        private readonly ConfigurationDbContext _configurationDbContext;

        public ApiResourcesManager(ConfigurationDbContext configurationDbContext)
        {
            _configurationDbContext = configurationDbContext;
        }

        /// <summary>
        /// 数据列表页
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Authorize]
        public async Task<IActionResult> Index()
        {
            return View(await _configurationDbContext.ApiResources
                .Include(d => d.UserClaims)
                .Include(d => d.Scopes)
                .ToListAsync());
        }

        /// <summary>
        /// 数据修改页
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet]
        [Authorize(Policy = "SuperAdmin")]
        public IActionResult CreateOrEdit(int id)
        {
            ViewBag.ApiResourceId = id;
            return View();
        }


        [HttpGet]
        [Authorize(Policy = "SuperAdmin")]
        public async Task<MessageModel<ApiResourceDto>> GetDataById(int id = 0)
        {
            var model = (await _configurationDbContext.ApiResources
                .Include(d => d.UserClaims)
                .Include(d => d.Scopes)
                .ToListAsync()).FirstOrDefault(d => d.Id == id).ToModel();

            var apiResourceDto = new ApiResourceDto();
            if (model != null)
            {
                apiResourceDto = new ApiResourceDto()
                {
                    Name = model?.Name,
                    DisplayName = model?.DisplayName,
                    Description = model?.Description,
                    UserClaims = string.Join(",", model?.UserClaims),
                    Scopes = string.Join(",", model?.Scopes),
                };
            }

            return new MessageModel<ApiResourceDto>()
            {
                success = true,
                msg = "获取成功",
                response = apiResourceDto
            };
        }

        [HttpPost]
        [Authorize(Policy = "SuperAdmin")]
        public async Task<MessageModel<string>> SaveData(ApiResourceDto request)
        {
            if (request != null && request.Id == 0)
            {
                IdentityServer4.Models.ApiResource apiResource = new IdentityServer4.Models.ApiResource()
                {
                    Name = request?.Name,
                    DisplayName = request?.DisplayName,
                    Description = request?.Description,
                    Enabled = true,
                    UserClaims = request?.UserClaims?.Split(","),
                    Scopes = request?.Scopes?.Split(","),
                };

                var result = (await _configurationDbContext.ApiResources.AddAsync(apiResource.ToEntity()));
                await _configurationDbContext.SaveChangesAsync();
            }

            if (request != null && request.Id > 0)
            {

                var modelEF = (await _configurationDbContext.ApiResources
                    .Include(d => d.UserClaims)
                    .Include(d => d.Scopes)
                    .ToListAsync()).FirstOrDefault(d => d.Id == request.Id);

                modelEF.Name = request?.Name;
                modelEF.DisplayName = request?.DisplayName;
                modelEF.Description = request?.Description;

                {
                    var apiResourceClaim = new List<IdentityServer4.EntityFramework.Entities.ApiResourceClaim>();
                    if (!string.IsNullOrEmpty(request?.UserClaims))
                    {
                        request?.UserClaims.Split(",").Where(s => s != "" && s != null).ToList().ForEach(s =>
                        {
                            apiResourceClaim.Add(new IdentityServer4.EntityFramework.Entities.ApiResourceClaim()
                            {
                                ApiResource = modelEF,
                                ApiResourceId = modelEF.Id,
                                Type = s
                            });
                        });
                        modelEF.UserClaims = apiResourceClaim;
                    }
                }


                var apiResourceScopes = new List<IdentityServer4.EntityFramework.Entities.ApiResourceScope>();
                if (!string.IsNullOrEmpty(request?.Scopes))
                {
                    request?.Scopes.Split(",").Where(s => s != "" && s != null).ToList().ForEach(s =>
                    {
                        apiResourceScopes.Add(new IdentityServer4.EntityFramework.Entities.ApiResourceScope()
                        {
                            ApiResource = modelEF,
                            ApiResourceId = modelEF.Id,
                            Scope = s
                        });
                    });
                    modelEF.Scopes = apiResourceScopes;
                }


                var result = (_configurationDbContext.ApiResources.Update(modelEF));
                await _configurationDbContext.SaveChangesAsync();
            }


            return new MessageModel<string>()
            {
                success = true,
                msg = "添加成功",
            };
        }

    }
}


================================================
FILE: Blog.IdentityServer/Controllers/Client/ClientDto.cs
================================================
namespace Blog.IdentityServer.Controllers.Client
{
    public class ClientDto
    {
        public int id { get; set; }
        public string ClientId { get; set; }
        public string ClientName { get; set; }
        public string ClientSecrets { get; set; }
        public string Description { get; set; }
        public string AllowAccessTokensViaBrowser { get; set; }
        public string AllowedGrantTypes { get; set; }
        public string AllowedScopes { get; set; }
        public string AllowedCorsOrigins { get; set; }
        public string RedirectUris { get; set; }
        public string PostLogoutRedirectUris { get; set; }
    }
}

================================================
FILE: Blog.IdentityServer/Controllers/Client/ClientsManagerController.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Blog.Core.Common.Helper;
using Blog.IdentityServer.Models;
using IdentityServer4;
using IdentityServer4.EntityFramework.DbContexts;
using IdentityServer4.EntityFramework.Mappers;
using IdentityServer4.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using static IdentityModel.OidcConstants;

namespace Blog.IdentityServer.Controllers.Client
{
    [Route("[controller]/[action]")]
    [ApiController]
    public class ClientsManagerController : Controller
    {
        private readonly ConfigurationDbContext _configurationDbContext;

        public ClientsManagerController(ConfigurationDbContext configurationDbContext)
        {
            _configurationDbContext = configurationDbContext;
        }

        /// <summary>
        /// 数据列表页
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Authorize]
        public async Task<IActionResult> Index()
        {
            return View(await _configurationDbContext.Clients
                .Include(d => d.AllowedGrantTypes)
                .Include(d => d.AllowedScopes)
                .Include(d => d.AllowedCorsOrigins)
                .Include(d => d.RedirectUris)
                .Include(d => d.PostLogoutRedirectUris)
                .ToListAsync());
        }

        /// <summary>
        /// 数据修改页
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet]
        [Authorize(Policy = "SuperAdmin")]
        public IActionResult CreateOrEdit(int id)
        {
            ViewBag.ClientId = id;
            return View();
        }


        [HttpGet]
        [Authorize(Policy = "SuperAdmin")]
        public async Task<MessageModel<ClientDto>> GetDataById(int id = 0)
        {
            var model = (await _configurationDbContext.Clients
                .Include(d => d.AllowedGrantTypes)
                .Include(d => d.AllowedScopes)
                .Include(d => d.AllowedCorsOrigins)
                .Include(d => d.RedirectUris)
                .Include(d => d.PostLogoutRedirectUris)
                .Include(d => d.ClientSecrets)
                .ToListAsync()).FirstOrDefault(d => d.Id == id).ToModel();

            var clientDto = new ClientDto();
            if (model != null)
            {
                clientDto = new ClientDto()
                {
                    ClientId = model?.ClientId,
                    ClientName = model?.ClientName,
                    Description = model?.Description,
                    AllowAccessTokensViaBrowser = (model?.AllowAccessTokensViaBrowser).ObjToString(),
                    AllowedCorsOrigins = string.Join(",", model?.AllowedCorsOrigins),
                    AllowedGrantTypes = string.Join(",", model?.AllowedGrantTypes),
                    AllowedScopes = string.Join(",", model?.AllowedScopes),
                    PostLogoutRedirectUris = string.Join(",", model?.PostLogoutRedirectUris),
                    RedirectUris = string.Join(",", model?.RedirectUris),
                    ClientSecrets = string.Join(",", model?.ClientSecrets.Select(d => d.Value)),
                };
            }

            return new MessageModel<ClientDto>()
            {
                success = true,
                msg = "获取成功",
                response = clientDto
            };
        }

        [HttpPost]
        [Authorize(Policy = "SuperAdmin")]
        public async Task<MessageModel<string>> SaveData(ClientDto request)
        {
            if (request != null && request.id == 0)
            {
                IdentityServer4.Models.Client client = new IdentityServer4.Models.Client()
                {
                    ClientId = request?.ClientId,
                    ClientName = request?.ClientName,
                    Description = request?.Description,
                    AllowAccessTokensViaBrowser = (request?.AllowAccessTokensViaBrowser).ObjToBool(),
                    AllowedCorsOrigins = request?.AllowedCorsOrigins?.Split(","),
                    AllowedGrantTypes = request?.AllowedGrantTypes?.Split(","),
                    AllowedScopes = request?.AllowedScopes?.Split(","),
                    PostLogoutRedirectUris = request?.PostLogoutRedirectUris?.Split(","),
                    RedirectUris = request?.RedirectUris?.Split(","),
                };

                if (!string.IsNullOrEmpty(request.ClientSecrets))
                {
                    client.ClientSecrets = new List<Secret>() { new Secret(request.ClientSecrets.Sha256()) };
                }

                var result = (await _configurationDbContext.Clients.AddAsync(client.ToEntity()));
                await _configurationDbContext.SaveChangesAsync();
            }

            if (request != null && request.id > 0)
            {

                var modelEF = (await _configurationDbContext.Clients
                    .Include(d => d.AllowedGrantTypes)
                    .Include(d => d.AllowedScopes)
                    .Include(d => d.AllowedCorsOrigins)
                    .Include(d => d.RedirectUris)
                    .Include(d => d.PostLogoutRedirectUris)
                    .ToListAsync()).FirstOrDefault(d => d.Id == request.id);

                modelEF.ClientId = request?.ClientId;
                modelEF.ClientName = request?.ClientName;
                modelEF.Description = request?.Description;
                modelEF.AllowAccessTokensViaBrowser = (request?.AllowAccessTokensViaBrowser).ObjToBool();

                var AllowedCorsOrigins = new List<IdentityServer4.EntityFramework.Entities.ClientCorsOrigin>();
                if (!string.IsNullOrEmpty(request?.AllowedCorsOrigins))
                {
                    request?.AllowedCorsOrigins.Split(",").Where(s => s != "" && s != null).ToList().ForEach(s =>
                               {
                                   AllowedCorsOrigins.Add(new IdentityServer4.EntityFramework.Entities.ClientCorsOrigin()
                                   {
                                       Client = modelEF,
                                       ClientId = modelEF.Id,
                                       Origin = s
                                   });
                               });
                    modelEF.AllowedCorsOrigins = AllowedCorsOrigins;
                }



                var AllowedGrantTypes = new List<IdentityServer4.EntityFramework.Entities.ClientGrantType>();
                if (!string.IsNullOrEmpty(request?.AllowedGrantTypes))
                {
                    request?.AllowedGrantTypes.Split(",").Where(s => s != "" && s != null).ToList().ForEach(s =>
                    {
                        AllowedGrantTypes.Add(new IdentityServer4.EntityFramework.Entities.ClientGrantType()
                        {
                            Client = modelEF,
                            ClientId = modelEF.Id,
                            GrantType = s
                        });
                    });
                    modelEF.AllowedGrantTypes = AllowedGrantTypes;
                }



                var AllowedScopes = new List<IdentityServer4.EntityFramework.Entities.ClientScope>();
                if (!string.IsNullOrEmpty(request?.AllowedScopes))
                {
                    request?.AllowedScopes.Split(",").Where(s => s != "" && s != null).ToList().ForEach(s =>
                    {
                        AllowedScopes.Add(new IdentityServer4.EntityFramework.Entities.ClientScope()
                        {
                            Client = modelEF,
                            ClientId = modelEF.Id,
                            Scope = s
                        });
                    });
                    modelEF.AllowedScopes = AllowedScopes;
                }


                var PostLogoutRedirectUris = new List<IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri>();
                if (!string.IsNullOrEmpty(request?.PostLogoutRedirectUris))
                {
                    request?.PostLogoutRedirectUris.Split(",").Where(s => s != "" && s != null).ToList().ForEach(s =>
                    {
                        PostLogoutRedirectUris.Add(new IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri()
                        {
                            Client = modelEF,
                            ClientId = modelEF.Id,
                            PostLogoutRedirectUri = s
                        });
                    });
                    modelEF.PostLogoutRedirectUris = PostLogoutRedirectUris;
                }


                var RedirectUris = new List<IdentityServer4.EntityFramework.Entities.ClientRedirectUri>();
                if (!string.IsNullOrEmpty(request?.RedirectUris))
                {
                    request?.RedirectUris.Split(",").Where(s => s != "" && s != null).ToList().ForEach(s =>
                    {
                        RedirectUris.Add(new IdentityServer4.EntityFramework.Entities.ClientRedirectUri()
                        {
                            Client = modelEF,
                            ClientId = modelEF.Id,
                            RedirectUri = s
                        });
                    });
                    modelEF.RedirectUris = RedirectUris;
                }

                var result = (_configurationDbContext.Clients.Update(modelEF));
                await _configurationDbContext.SaveChangesAsync();
            }


            return new MessageModel<string>()
            {
                success = true,
                msg = "添加成功",
            };
        }
    }
}

================================================
FILE: Blog.IdentityServer/Controllers/Consent/ConsentController.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


using IdentityServer4.Events;
using IdentityServer4.Models;
using IdentityServer4.Services;
using IdentityServer4.Extensions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System.Linq;
using System.Threading.Tasks;
using IdentityServer4.Validation;
using System.Collections.Generic;
using System;

namespace IdentityServer4.Quickstart.UI
{
    /// <summary>
    /// This controller processes the consent UI
    /// </summary>
    [SecurityHeaders]
    [Authorize]
    public class ConsentController : Controller
    {
        private readonly IIdentityServerInteractionService _interaction;
        private readonly IEventService _events;
        private readonly ILogger<ConsentController> _logger;

        public ConsentController(
            IIdentityServerInteractionService interaction,
            IEventService events,
            ILogger<ConsentController> logger)
        {
            _interaction = interaction;
            _events = events;
            _logger = logger;
        }

        /// <summary>
        /// Shows the consent screen
        /// </summary>
        /// <param name="returnUrl"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<IActionResult> Index(string returnUrl)
        {
            var vm = await BuildViewModelAsync(returnUrl);
            if (vm != null)
            {
                return View("Index", vm);
            }

            return View("Error");
        }

        /// <summary>
        /// Handles the consent screen postback
        /// </summary>
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Index(ConsentInputModel model)
        {
            var result = await ProcessConsent(model);

            if (result.IsRedirect)
            {
                var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl);
                if (context?.IsNativeClient() == true)
                {
                    // The client is native, so this change in how to
                    // return the response is for better UX for the end user.
                    return this.LoadingPage("Redirect", result.RedirectUri);
                }

                return Redirect(result.RedirectUri);
            }

            if (result.HasValidationError)
            {
                ModelState.AddModelError(string.Empty, result.ValidationError);
            }

            if (result.ShowView)
            {
                return View("Index", result.ViewModel);
            }

            return View("Error");
        }

        /*****************************************/
        /* helper APIs for the ConsentController */
        /*****************************************/
        private async Task<ProcessConsentResult> ProcessConsent(ConsentInputModel model)
        {
            var result = new ProcessConsentResult();

            // validate return url is still valid
            var request = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl);
            if (request == null) return result;

            ConsentResponse grantedConsent = null;

            // user clicked 'no' - send back the standard 'access_denied' response
            if (model?.Button == "no")
            {
                grantedConsent = new ConsentResponse { Error = AuthorizationError.AccessDenied };

                // emit event
                await _events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues));
            }
            // user clicked 'yes' - validate the data
            else if (model?.Button == "yes")
            {
                // if the user consented to some scope, build the response model
                if (model.ScopesConsented != null && model.ScopesConsented.Any())
                {
                    var scopes = model.ScopesConsented;
                    if (ConsentOptions.EnableOfflineAccess == false)
                    {
                        scopes = scopes.Where(x => x != IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess);
                    }

                    grantedConsent = new ConsentResponse
                    {
                        RememberConsent = model.RememberConsent,
                        ScopesValuesConsented = scopes.ToArray(),
                        Description = model.Description
                    };

                    // emit event
                    await _events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues, grantedConsent.ScopesValuesConsented, grantedConsent.RememberConsent));
                }
                else
                {
                    result.ValidationError = ConsentOptions.MustChooseOneErrorMessage;
                }
            }
            else
            {
                result.ValidationError = ConsentOptions.InvalidSelectionErrorMessage;
            }

            if (grantedConsent != null)
            {
                // communicate outcome of consent back to identityserver
                await _interaction.GrantConsentAsync(request, grantedConsent);

                // indicate that's it ok to redirect back to authorization endpoint
                result.RedirectUri = model.ReturnUrl;
                result.Client = request.Client;
            }
            else
            {
                // we need to redisplay the consent UI
                result.ViewModel = await BuildViewModelAsync(model.ReturnUrl, model);
            }

            return result;
        }

        private async Task<ConsentViewModel> BuildViewModelAsync(string returnUrl, ConsentInputModel model = null)
        {
            var request = await _interaction.GetAuthorizationContextAsync(returnUrl);
            if (request != null)
            {
                return CreateConsentViewModel(model, returnUrl, request);
            }
            else
            {
                _logger.LogError("No consent request matching request: {0}", returnUrl);
            }

            return null;
        }

        private ConsentViewModel CreateConsentViewModel(
            ConsentInputModel model, string returnUrl,
            AuthorizationRequest request)
        {
            var vm = new ConsentViewModel
            {
                RememberConsent = model?.RememberConsent ?? true,
                ScopesConsented = model?.ScopesConsented ?? Enumerable.Empty<string>(),
                Description = model?.Description,

                ReturnUrl = returnUrl,

                ClientName = request.Client.ClientName ?? request.Client.ClientId,
                ClientUrl = request.Client.ClientUri,
                ClientLogoUrl = request.Client.LogoUri,
                AllowRememberConsent = request.Client.AllowRememberConsent
            };

            vm.IdentityScopes = request.ValidatedResources.Resources.IdentityResources.Select(x => CreateScopeViewModel(x, vm.ScopesConsented.Contains(x.Name) || model == null)).ToArray();

            var apiScopes = new List<ScopeViewModel>();
            foreach (var parsedScope in request.ValidatedResources.ParsedScopes)
            {
                var apiScope = request.ValidatedResources.Resources.FindApiScope(parsedScope.ParsedName);
                if (apiScope != null)
                {
                    var scopeVm = CreateScopeViewModel(parsedScope, apiScope, vm.ScopesConsented.Contains(parsedScope.RawValue) || model == null);
                    apiScopes.Add(scopeVm);
                }
            }
            if (ConsentOptions.EnableOfflineAccess && request.ValidatedResources.Resources.OfflineAccess)
            {
                apiScopes.Add(GetOfflineAccessScope(vm.ScopesConsented.Contains(IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess) || model == null));
            }
            vm.ApiScopes = apiScopes;

            return vm;
        }

        private ScopeViewModel CreateScopeViewModel(IdentityResource identity, bool check)
        {
            return new ScopeViewModel
            {
                Value = identity.Name,
                DisplayName = identity.DisplayName ?? identity.Name,
                Description = identity.Description,
                Emphasize = identity.Emphasize,
                Required = identity.Required,
                Checked = check || identity.Required
            };
        }

        public ScopeViewModel CreateScopeViewModel(ParsedScopeValue parsedScopeValue, ApiScope apiScope, bool check)
        {
            var displayName = apiScope.DisplayName ?? apiScope.Name;
            if (!String.IsNullOrWhiteSpace(parsedScopeValue.ParsedParameter))
            {
                displayName += ":" + parsedScopeValue.ParsedParameter;
            }

            return new ScopeViewModel
            {
                Value = parsedScopeValue.RawValue,
                DisplayName = displayName,
                Description = apiScope.Description,
                Emphasize = apiScope.Emphasize,
                Required = apiScope.Required,
                Checked = check || apiScope.Required
            };
        }

        private ScopeViewModel GetOfflineAccessScope(bool check)
        {
            return new ScopeViewModel
            {
                Value = IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess,
                DisplayName = ConsentOptions.OfflineAccessDisplayName,
                Description = ConsentOptions.OfflineAccessDescription,
                Emphasize = true,
                Checked = check
            };
        }
    }
}

================================================
FILE: Blog.IdentityServer/Controllers/Consent/ConsentInputModel.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


using System.Collections.Generic;

namespace IdentityServer4.Quickstart.UI
{
    public class ConsentInputModel
    {
        public string Button { get; set; }
        public IEnumerable<string> ScopesConsented { get; set; }
        public bool RememberConsent { get; set; }
        public string ReturnUrl { get; set; }
        public string Description { get; set; }
    }
}

================================================
FILE: Blog.IdentityServer/Controllers/Consent/ConsentOptions.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


namespace IdentityServer4.Quickstart.UI
{
    public class ConsentOptions
    {
        public static bool EnableOfflineAccess = true;
        public static string OfflineAccessDisplayName = "Offline Access";
        public static string OfflineAccessDescription = "Access to your applications and resources, even when you are offline";

        public static readonly string MustChooseOneErrorMessage = "You must pick at least one permission";
        public static readonly string InvalidSelectionErrorMessage = "Invalid selection";
    }
}


================================================
FILE: Blog.IdentityServer/Controllers/Consent/ConsentViewModel.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


using System.Collections.Generic;

namespace IdentityServer4.Quickstart.UI
{
    public class ConsentViewModel : ConsentInputModel
    {
        public string ClientName { get; set; }
        public string ClientUrl { get; set; }
        public string ClientLogoUrl { get; set; }
        public bool AllowRememberConsent { get; set; }

        public IEnumerable<ScopeViewModel> IdentityScopes { get; set; }
        public IEnumerable<ScopeViewModel> ApiScopes { get; set; }
    }
}


================================================
FILE: Blog.IdentityServer/Controllers/Consent/ProcessConsentResult.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.

using IdentityServer4.Models;

namespace IdentityServer4.Quickstart.UI
{
    public class ProcessConsentResult
    {
        public bool IsRedirect => RedirectUri != null;
        public string RedirectUri { get; set; }
        public Client Client { get; set; }

        public bool ShowView => ViewModel != null;
        public ConsentViewModel ViewModel { get; set; }

        public bool HasValidationError => ValidationError != null;
        public string ValidationError { get; set; }
    }
}


================================================
FILE: Blog.IdentityServer/Controllers/Consent/ScopeViewModel.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


namespace IdentityServer4.Quickstart.UI
{
    public class ScopeViewModel
    {
        public string Value { get; set; }
        public string DisplayName { get; set; }
        public string Description { get; set; }
        public bool Emphasize { get; set; }
        public bool Required { get; set; }
        public bool Checked { get; set; }
    }
}


================================================
FILE: Blog.IdentityServer/Controllers/Device/DeviceAuthorizationInputModel.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


namespace IdentityServer4.Quickstart.UI.Device
{
    public class DeviceAuthorizationInputModel : ConsentInputModel
    {
        public string UserCode { get; set; }
    }
}

================================================
FILE: Blog.IdentityServer/Controllers/Device/DeviceAuthorizationViewModel.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


namespace IdentityServer4.Quickstart.UI.Device
{
    public class DeviceAuthorizationViewModel : ConsentViewModel
    {
        public string UserCode { get; set; }
        public bool ConfirmUserCode { get; set; }
    }
}

================================================
FILE: Blog.IdentityServer/Controllers/Device/DeviceController.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IdentityServer4.Configuration;
using IdentityServer4.Events;
using IdentityServer4.Extensions;
using IdentityServer4.Models;
using IdentityServer4.Services;
using IdentityServer4.Validation;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace IdentityServer4.Quickstart.UI.Device
{
    [Authorize]
    [SecurityHeaders]
    public class DeviceController : Controller
    {
        private readonly IDeviceFlowInteractionService _interaction;
        private readonly IEventService _events;
        private readonly IOptions<IdentityServerOptions> _options;
        private readonly ILogger<DeviceController> _logger;

        public DeviceController(
            IDeviceFlowInteractionService interaction,
            IEventService eventService,
            IOptions<IdentityServerOptions> options,
            ILogger<DeviceController> logger)
        {
            _interaction = interaction;
            _events = eventService;
            _options = options;
            _logger = logger;
        }

        [HttpGet]
        public async Task<IActionResult> Index()
        {
            string userCodeParamName = _options.Value.UserInteraction.DeviceVerificationUserCodeParameter;
            string userCode = Request.Query[userCodeParamName];
            if (string.IsNullOrWhiteSpace(userCode)) return View("UserCodeCapture");

            var vm = await BuildViewModelAsync(userCode);
            if (vm == null) return View("Error");

            vm.ConfirmUserCode = true;
            return View("UserCodeConfirmation", vm);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> UserCodeCapture(string userCode)
        {
            var vm = await BuildViewModelAsync(userCode);
            if (vm == null) return View("Error");

            return View("UserCodeConfirmation", vm);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Callback(DeviceAuthorizationInputModel model)
        {
            if (model == null) throw new ArgumentNullException(nameof(model));

            var result = await ProcessConsent(model);
            if (result.HasValidationError) return View("Error");

            return View("Success");
        }

        private async Task<ProcessConsentResult> ProcessConsent(DeviceAuthorizationInputModel model)
        {
            var result = new ProcessConsentResult();

            var request = await _interaction.GetAuthorizationContextAsync(model.UserCode);
            if (request == null) return result;

            ConsentResponse grantedConsent = null;

            // user clicked 'no' - send back the standard 'access_denied' response
            if (model.Button == "no")
            {
                grantedConsent = new ConsentResponse { Error = AuthorizationError.AccessDenied };

                // emit event
                await _events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues));
            }
            // user clicked 'yes' - validate the data
            else if (model.Button == "yes")
            {
                // if the user consented to some scope, build the response model
                if (model.ScopesConsented != null && model.ScopesConsented.Any())
                {
                    var scopes = model.ScopesConsented;
                    if (ConsentOptions.EnableOfflineAccess == false)
                    {
                        scopes = scopes.Where(x => x != IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess);
                    }

                    grantedConsent = new ConsentResponse
                    {
                        RememberConsent = model.RememberConsent,
                        ScopesValuesConsented = scopes.ToArray(),
                        Description = model.Description
                    };

                    // emit event
                    await _events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues, grantedConsent.ScopesValuesConsented, grantedConsent.RememberConsent));
                }
                else
                {
                    result.ValidationError = ConsentOptions.MustChooseOneErrorMessage;
                }
            }
            else
            {
                result.ValidationError = ConsentOptions.InvalidSelectionErrorMessage;
            }

            if (grantedConsent != null)
            {
                // communicate outcome of consent back to identityserver
                await _interaction.HandleRequestAsync(model.UserCode, grantedConsent);

                // indicate that's it ok to redirect back to authorization endpoint
                result.RedirectUri = model.ReturnUrl;
                result.Client = request.Client;
            }
            else
            {
                // we need to redisplay the consent UI
                result.ViewModel = await BuildViewModelAsync(model.UserCode, model);
            }

            return result;
        }

        private async Task<DeviceAuthorizationViewModel> BuildViewModelAsync(string userCode, DeviceAuthorizationInputModel model = null)
        {
            var request = await _interaction.GetAuthorizationContextAsync(userCode);
            if (request != null)
            {
                return CreateConsentViewModel(userCode, model, request);
            }

            return null;
        }

        private DeviceAuthorizationViewModel CreateConsentViewModel(string userCode, DeviceAuthorizationInputModel model, DeviceFlowAuthorizationRequest request)
        {
            var vm = new DeviceAuthorizationViewModel
            {
                UserCode = userCode,
                Description = model?.Description,

                RememberConsent = model?.RememberConsent ?? true,
                ScopesConsented = model?.ScopesConsented ?? Enumerable.Empty<string>(),

                ClientName = request.Client.ClientName ?? request.Client.ClientId,
                ClientUrl = request.Client.ClientUri,
                ClientLogoUrl = request.Client.LogoUri,
                AllowRememberConsent = request.Client.AllowRememberConsent
            };

            vm.IdentityScopes = request.ValidatedResources.Resources.IdentityResources.Select(x => CreateScopeViewModel(x, vm.ScopesConsented.Contains(x.Name) || model == null)).ToArray();

            var apiScopes = new List<ScopeViewModel>();
            foreach (var parsedScope in request.ValidatedResources.ParsedScopes)
            {
                var apiScope = request.ValidatedResources.Resources.FindApiScope(parsedScope.ParsedName);
                if (apiScope != null)
                {
                    var scopeVm = CreateScopeViewModel(parsedScope, apiScope, vm.ScopesConsented.Contains(parsedScope.RawValue) || model == null);
                    apiScopes.Add(scopeVm);
                }
            }
            if (ConsentOptions.EnableOfflineAccess && request.ValidatedResources.Resources.OfflineAccess)
            {
                apiScopes.Add(GetOfflineAccessScope(vm.ScopesConsented.Contains(IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess) || model == null));
            }
            vm.ApiScopes = apiScopes;

            return vm;
        }

        private ScopeViewModel CreateScopeViewModel(IdentityResource identity, bool check)
        {
            return new ScopeViewModel
            {
                Value = identity.Name,
                DisplayName = identity.DisplayName ?? identity.Name,
                Description = identity.Description,
                Emphasize = identity.Emphasize,
                Required = identity.Required,
                Checked = check || identity.Required
            };
        }

        public ScopeViewModel CreateScopeViewModel(ParsedScopeValue parsedScopeValue, ApiScope apiScope, bool check)
        {
            return new ScopeViewModel
            {
                Value = parsedScopeValue.RawValue,
                // todo: use the parsed scope value in the display?
                DisplayName = apiScope.DisplayName ?? apiScope.Name,
                Description = apiScope.Description,
                Emphasize = apiScope.Emphasize,
                Required = apiScope.Required,
                Checked = check || apiScope.Required
            };
        }
        private ScopeViewModel GetOfflineAccessScope(bool check)
        {
            return new ScopeViewModel
            {
                Value = IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess,
                DisplayName = ConsentOptions.OfflineAccessDisplayName,
                Description = ConsentOptions.OfflineAccessDescription,
                Emphasize = true,
                Checked = check
            };
        }
    }
}

================================================
FILE: Blog.IdentityServer/Controllers/Diagnostics/DiagnosticsController.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace IdentityServer4.Quickstart.UI
{
    [SecurityHeaders]
    [Authorize]
    public class DiagnosticsController : Controller
    {
        public async Task<IActionResult> Index()
        {
            var localAddresses = new string[] { "127.0.0.1", "::1", HttpContext.Connection.LocalIpAddress.ToString() };
            if (!localAddresses.Contains(HttpContext.Connection.RemoteIpAddress.ToString()))
            {
                return NotFound();
            }

            var model = new DiagnosticsViewModel(await HttpContext.AuthenticateAsync());
            return View(model);
        }
    }
}

================================================
FILE: Blog.IdentityServer/Controllers/Diagnostics/DiagnosticsViewModel.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


using IdentityModel;
using Microsoft.AspNetCore.Authentication;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Text;

namespace IdentityServer4.Quickstart.UI
{
    public class DiagnosticsViewModel
    {
        public DiagnosticsViewModel(AuthenticateResult result)
        {
            AuthenticateResult = result;

            if (result.Properties.Items.ContainsKey("client_list"))
            {
                var encoded = result.Properties.Items["client_list"];
                var bytes = Base64Url.Decode(encoded);
                var value = Encoding.UTF8.GetString(bytes);

                Clients = JsonConvert.DeserializeObject<string[]>(value);
            }
        }

        public AuthenticateResult AuthenticateResult { get; }
        public IEnumerable<string> Clients { get; } = new List<string>();
    }
}

================================================
FILE: Blog.IdentityServer/Controllers/Extensions.cs
================================================
using System;
using System.Threading.Tasks;
using IdentityServer4.Models;
using IdentityServer4.Stores;
using Microsoft.AspNetCore.Mvc;

namespace IdentityServer4.Quickstart.UI
{
    public static class Extensions
    {
        /// <summary>
        /// Determines whether the client is configured to use PKCE.
        /// </summary>
        /// <param name="store">The store.</param>
        /// <param name="client_id">The client identifier.</param>
        /// <returns></returns>
        public static async Task<bool> IsPkceClientAsync(this IClientStore store, string client_id)
        {
            if (!string.IsNullOrWhiteSpace(client_id))
            {
                var client = await store.FindEnabledClientByIdAsync(client_id);
                return client?.RequirePkce == true;
            }

            return false;
        }

        /// <summary>
        /// Checks if the redirect URI is for a native client.
        /// </summary>
        /// <returns></returns>
        public static bool IsNativeClient(this AuthorizationRequest context)
        {
            return !context.RedirectUri.StartsWith("https", StringComparison.Ordinal)
               && !context.RedirectUri.StartsWith("http", StringComparison.Ordinal);
        }

        public static IActionResult LoadingPage(this Controller controller, string viewName, string redirectUri)
        {
            controller.HttpContext.Response.StatusCode = 200;
            controller.HttpContext.Response.Headers["Location"] = "";

            return controller.View(viewName, new RedirectViewModel { RedirectUrl = redirectUri });
        }
    }
}


================================================
FILE: Blog.IdentityServer/Controllers/Grants/GrantsController.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


using IdentityServer4.Services;
using IdentityServer4.Stores;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using IdentityServer4.Events;
using IdentityServer4.Extensions;

namespace IdentityServer4.Quickstart.UI
{
    /// <summary>
    /// This sample controller allows a user to revoke grants given to clients
    /// </summary>
    [SecurityHeaders]
    [Authorize]
    public class GrantsController : Controller
    {
        private readonly IIdentityServerInteractionService _interaction;
        private readonly IClientStore _clients;
        private readonly IResourceStore _resources;
        private readonly IEventService _events;

        public GrantsController(IIdentityServerInteractionService interaction,
            IClientStore clients,
            IResourceStore resources,
            IEventService events)
        {
            _interaction = interaction;
            _clients = clients;
            _resources = resources;
            _events = events;
        }

        /// <summary>
        /// Show list of grants
        /// </summary>
        [HttpGet]
        public async Task<IActionResult> Index()
        {
            return View("Index", await BuildViewModelAsync());
        }

        /// <summary>
        /// Handle postback to revoke a client
        /// </summary>
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Revoke(string clientId)
        {
            await _interaction.RevokeUserConsentAsync(clientId);
            await _events.RaiseAsync(new GrantsRevokedEvent(User.GetSubjectId(), clientId));

            return RedirectToAction("Index");
        }

        private async Task<GrantsViewModel> BuildViewModelAsync()
        {
            var grants = await _interaction.GetAllUserGrantsAsync();

            var list = new List<GrantViewModel>();
            foreach (var grant in grants)
            {
                var client = await _clients.FindClientByIdAsync(grant.ClientId);
                if (client != null)
                {
                    var resources = await _resources.FindResourcesByScopeAsync(grant.Scopes);

                    var item = new GrantViewModel()
                    {
                        ClientId = client.ClientId,
                        ClientName = client.ClientName ?? client.ClientId,
                        ClientLogoUrl = client.LogoUri,
                        ClientUrl = client.ClientUri,
                        Description = grant.Description,
                        Created = grant.CreationTime,
                        Expires = grant.Expiration,
                        IdentityGrantNames = resources.IdentityResources.Select(x => x.DisplayName ?? x.Name).ToArray(),
                        ApiGrantNames = resources.ApiScopes.Select(x => x.DisplayName ?? x.Name).ToArray()
                    };

                    list.Add(item);
                }
            }

            return new GrantsViewModel
            {
                Grants = list
            };
        }


        [HttpGet]
        [AllowAnonymous]
        public IActionResult Config()
        {
            return View();
        }
    }
}

================================================
FILE: Blog.IdentityServer/Controllers/Grants/GrantsViewModel.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


using System;
using System.Collections.Generic;

namespace IdentityServer4.Quickstart.UI
{
    public class GrantsViewModel
    {
        public IEnumerable<GrantViewModel> Grants { get; set; }
    }

    public class GrantViewModel
    {
        public string ClientId { get; set; }
        public string ClientName { get; set; }
        public string ClientUrl { get; set; }
        public string ClientLogoUrl { get; set; }
        public string Description { get; set; }
        public DateTime Created { get; set; }
        public DateTime? Expires { get; set; }
        public IEnumerable<string> IdentityGrantNames { get; set; }
        public IEnumerable<string> ApiGrantNames { get; set; }
    }
}

================================================
FILE: Blog.IdentityServer/Controllers/Home/ErrorViewModel.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


using IdentityServer4.Models;

namespace IdentityServer4.Quickstart.UI
{
    public class ErrorViewModel
    {
        public ErrorMessage Error { get; set; }
    }
}

================================================
FILE: Blog.IdentityServer/Controllers/Home/HomeController.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


using IdentityServer4.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

namespace IdentityServer4.Quickstart.UI
{
    [SecurityHeaders]
    [AllowAnonymous]
    public class HomeController : Controller
    {
        private readonly IIdentityServerInteractionService _interaction;
        private readonly IWebHostEnvironment _environment;
        private readonly ILogger _logger;

        public HomeController(IIdentityServerInteractionService interaction, IWebHostEnvironment environment, ILogger<HomeController> logger)
        {
            _interaction = interaction;
            _environment = environment;
            _logger = logger;
        }

        public IActionResult Index()
        {
            return View();

            //if (_environment.IsDevelopment())
            //{
            //    // only show in development
            //    return View();
            //}

            //_logger.LogInformation("Homepage is disabled in production. Returning 404.");
            //return NotFound();
        }

        /// <summary>
        /// Shows the error page
        /// </summary>
        public async Task<IActionResult> Error(string errorId)
        {
            var vm = new ErrorViewModel();

            // retrieve error details from identityserver
            var message = await _interaction.GetErrorContextAsync(errorId);
            if (message != null)
            {
                vm.Error = message;

                if (!_environment.IsDevelopment())
                {
                    // only show in development
                    message.ErrorDescription = null;
                }
            }

            return View("Error", vm);
        }
    }
}

================================================
FILE: Blog.IdentityServer/Controllers/Home/Is4ApiController.cs
================================================
using Blog.IdentityServer.Models;
using Blog.IdentityServer.Models.ViewModel;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Blog.IdentityServer.Controllers
{
    [Route("[controller]/[action]")]
    [ApiController]
    public class Is4ApiController : ControllerBase
    {
        private readonly UserManager<ApplicationUser> _userManager;

        public Is4ApiController(UserManager<ApplicationUser> userManager)
        {
            _userManager = userManager;
        }


        [HttpGet]
        public MessageModel<AccessApiDateView> GetAchieveUsers()
        {
            List<ApiDate> apiDates = new List<ApiDate>();

            var users = _userManager.Users.Where(d => !d.tdIsDelete).OrderByDescending(d => d.Id).ToList();

            var tadayRegisterUser = users.Where(d => d.birth >= DateTime.Now.Date).Count();

            apiDates = (from n in users
                        group n by new { n.birth.Date } into g
                        select new ApiDate
                        {
                            date = g.Key?.Date.ToString("yyyy-MM-dd"),
                            count = g.Count(),
                        }).ToList();

            apiDates = apiDates.OrderByDescending(d => d.date).Take(30).ToList();


            if (apiDates.Count == 0)
            {
                apiDates.Add(new ApiDate()
                {
                    date = "没数据,或未开启相应接口服务",
                    count = 0
                });
            }
            return new MessageModel<AccessApiDateView>()
            {
                msg = "获取成功",
                success = true,
                response = new AccessApiDateView
                {
                    columns = new string[] { "date", "count" },
                    rows = apiDates.OrderBy(d => d.date).ToList(),
                    today = tadayRegisterUser,
                }
            };
        }
    }
}

================================================
FILE: Blog.IdentityServer/Controllers/SecurityHeadersAttribute.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace IdentityServer4.Quickstart.UI
{
    public class SecurityHeadersAttribute : ActionFilterAttribute
    {
        public override void OnResultExecuting(ResultExecutingContext context)
        {
            var result = context.Result;
            if (result is ViewResult)
            {
                // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
                if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Type-Options"))
                {
                    context.HttpContext.Response.Headers.Add("X-Content-Type-Options", "nosniff");
                }

                // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
                if (!context.HttpContext.Response.Headers.ContainsKey("X-Frame-Options"))
                {
                    context.HttpContext.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN");
                }

                // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
                var csp = "default-src 'self'; object-src 'none'; frame-ancestors 'none'; sandbox allow-forms allow-same-origin allow-scripts; base-uri 'self';";
                // also consider adding upgrade-insecure-requests once you have HTTPS in place for production
                //csp += "upgrade-insecure-requests;";
                // also an example if you need client images to be displayed from twitter
                // csp += "img-src 'self' https://pbs.twimg.com;";

                // once for standards compliant browsers
                if (!context.HttpContext.Response.Headers.ContainsKey("Content-Security-Policy"))
                {
                    context.HttpContext.Response.Headers.Add("Content-Security-Policy", csp);
                }
                // and once again for IE
                if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Security-Policy"))
                {
                    context.HttpContext.Response.Headers.Add("X-Content-Security-Policy", csp);
                }

                // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
                var referrer_policy = "no-referrer";
                if (!context.HttpContext.Response.Headers.ContainsKey("Referrer-Policy"))
                {
                    context.HttpContext.Response.Headers.Add("Referrer-Policy", referrer_policy);
                }
            }
        }
    }
}


================================================
FILE: Blog.IdentityServer/Controllers/TestUsers.cs
================================================
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.


using IdentityModel;
using IdentityServer4.Test;
using System.Collections.Generic;
using System.Security.Claims;

namespace IdentityServer4.Quickstart.UI
{
    public class TestUsers
    {
        public static List<TestUser> Users = new List<TestUser>
        {
            new TestUser{SubjectId = "818727", Username = "alice", Password = "alice", 
                Claims = 
                {
                    new Claim(JwtClaimTypes.Name, "Alice Smith"),
                    new Claim(JwtClaimTypes.GivenName, "Alice"),
                    new Claim(JwtClaimTypes.FamilyName, "Smith"),
                    new Claim(JwtClaimTypes.Email, "AliceSmith@email.com"),
                    new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
                    new Claim(JwtClaimTypes.WebSite, "http://alice.com"),
                    new Claim(JwtClaimTypes.Address, @"{ 'street_address': 'One Hacker Way', 'locality': 'Heidelberg', 'postal_code': 69118, 'country': 'Germany' }", IdentityServer4.IdentityServerConstants.ClaimValueTypes.Json)
                }
            },
            new TestUser{SubjectId = "88421113", Username = "bob", Password = "bob", 
                Claims = 
                {
                    new Claim(JwtClaimTypes.Name, "Bob Smith"),
                    new Claim(JwtClaimTypes.GivenName, "Bob"),
                    new Claim(JwtClaimTypes.FamilyName, "Smith"),
                    new Claim(JwtClaimTypes.Email, "BobSmith@email.com"),
                    new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
                    new Claim(JwtClaimTypes.WebSite, "http://bob.com"),
                    new Claim(JwtClaimTypes.Address, @"{ 'street_address': 'One Hacker Way', 'locality': 'Heidelberg', 'postal_code': 69118, 'country': 'Germany' }", IdentityServer4.IdentityServerConstants.ClaimValueTypes.Json),
                    new Claim("location", "somewhere")
                }
            }
        };
    }
}

================================================
FILE: Blog.IdentityServer/Data/ApplicationDbContext.cs
================================================
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Blog.IdentityServer.Models;
using Microsoft.AspNetCore.Identity;

namespace Blog.IdentityServer.Data
{
    //public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    //{
    //    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
    //        : base(options)
    //    {
    //    }

    //    protected override void OnModelCreating(ModelBuilder builder)
    //    {
    //        base.OnModelCreating(builder);
    //        // Customize the ASP.NET Identity model and override the defaults if needed.
    //        // For example, you can rename the ASP.NET Identity table names and more.
    //        // Add your customizations after calling base.OnModelCreating(builder);
    //    }
    //}

    public class ApplicationDbContext
    : IdentityDbContext<ApplicationUser, ApplicationRole, int, IdentityUserClaim<int>,
    ApplicationUserRole, IdentityUserLogin<int>,
    IdentityRoleClaim<int>, IdentityUserToken<int>>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);

            //builder.Entity<ApplicationUserRole>(userRole =>
            //{
            //    userRole.HasKey(ur => new { ur.UserId, ur.RoleId });

            //    userRole.HasOne(ur => ur.Role)
            //        .WithMany(r => r.UserRoles)
            //        .HasForeignKey(ur => ur.RoleId)
            //        .IsRequired();

            //    userRole.HasOne(ur => ur.User)
            //        .WithMany(r => r.UserRoles)
            //        .HasForeignKey(ur => ur.UserId)
            //        .IsRequired();
            //});

            //// 就是这里,我们可以修改下表名等其他任意操作
            //builder.Entity<ApplicationRole>()
            //    .ToTable("Role");
        }
    }
}


================================================
FILE: Blog.IdentityServer/Data/MigrationsMySql/20200509165505_AppDbMigration.Designer.cs
================================================
// <auto-generated />
using System;
using Blog.IdentityServer.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;

namespace Blog.IdentityServer.Data.MigrationsMySql
{
    [DbContext(typeof(ApplicationDbContext))]
    [Migration("20200509165505_AppDbMigration")]
    partial class AppDbMigration
    {
        protected override void BuildTargetModel(ModelBuilder modelBuilder)
        {
#pragma warning disable 612, 618
            modelBuilder
                .HasAnnotation("ProductVersion", "3.1.3")
                .HasAnnotation("Relational:MaxIdentifierLength", 64);

            modelBuilder.Entity("Blog.IdentityServer.Models.ApplicationRole", b =>
                {
                    b.Property<int>("Id")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("int");

                    b.Property<string>("ConcurrencyStamp")
                        .IsConcurrencyToken()
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<string>("CreateBy")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<int?>("CreateId")
                        .HasColumnType("int");

                    b.Property<DateTime?>("CreateTime")
                        .HasColumnType("datetime(6)");

                    b.Property<string>("Description")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<bool>("Enabled")
                        .HasColumnType("tinyint(1)");

                    b.Property<bool>("IsDeleted")
                        .HasColumnType("tinyint(1)");

                    b.Property<string>("ModifyBy")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<int?>("ModifyId")
                        .HasColumnType("int");

                    b.Property<DateTime?>("ModifyTime")
                        .HasColumnType("datetime(6)");

                    b.Property<string>("Name")
                        .HasColumnType("varchar(256) CHARACTER SET utf8mb4")
                        .HasMaxLength(256);

                    b.Property<string>("NormalizedName")
                        .HasColumnType("varchar(256) CHARACTER SET utf8mb4")
                        .HasMaxLength(256);

                    b.Property<int>("OrderSort")
                        .HasColumnType("int");

                    b.HasKey("Id");

                    b.HasIndex("NormalizedName")
                        .IsUnique()
                        .HasName("RoleNameIndex");

                    b.ToTable("AspNetRoles");
                });

            modelBuilder.Entity("Blog.IdentityServer.Models.ApplicationUser", b =>
                {
                    b.Property<int>("Id")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("int");

                    b.Property<int>("AccessFailedCount")
                        .HasColumnType("int");

                    b.Property<string>("ConcurrencyStamp")
                        .IsConcurrencyToken()
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<string>("Email")
                        .HasColumnType("varchar(256) CHARACTER SET utf8mb4")
                        .HasMaxLength(256);

                    b.Property<bool>("EmailConfirmed")
                        .HasColumnType("tinyint(1)");

                    b.Property<bool>("LockoutEnabled")
                        .HasColumnType("tinyint(1)");

                    b.Property<DateTimeOffset?>("LockoutEnd")
                        .HasColumnType("datetime(6)");

                    b.Property<string>("LoginName")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<string>("NormalizedEmail")
                        .HasColumnType("varchar(256) CHARACTER SET utf8mb4")
                        .HasMaxLength(256);

                    b.Property<string>("NormalizedUserName")
                        .HasColumnType("varchar(256) CHARACTER SET utf8mb4")
                        .HasMaxLength(256);

                    b.Property<string>("PasswordHash")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<string>("PhoneNumber")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<bool>("PhoneNumberConfirmed")
                        .HasColumnType("tinyint(1)");

                    b.Property<string>("RealName")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<string>("SecurityStamp")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<bool>("TwoFactorEnabled")
                        .HasColumnType("tinyint(1)");

                    b.Property<string>("UserName")
                        .HasColumnType("varchar(256) CHARACTER SET utf8mb4")
                        .HasMaxLength(256);

                    b.Property<string>("addr")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<int>("age")
                        .HasColumnType("int");

                    b.Property<DateTime>("birth")
                        .HasColumnType("datetime(6)");

                    b.Property<int>("sex")
                        .HasColumnType("int");

                    b.Property<bool>("tdIsDelete")
                        .HasColumnType("tinyint(1)");

                    b.HasKey("Id");

                    b.HasIndex("NormalizedEmail")
                        .HasName("EmailIndex");

                    b.HasIndex("NormalizedUserName")
                        .IsUnique()
                        .HasName("UserNameIndex");

                    b.ToTable("AspNetUsers");
                });

            modelBuilder.Entity("Blog.IdentityServer.Models.ApplicationUserRole", b =>
                {
                    b.Property<int>("UserId")
                        .HasColumnType("int");

                    b.Property<int>("RoleId")
                        .HasColumnType("int");

                    b.Property<int?>("RoleId1")
                        .HasColumnType("int");

                    b.Property<int?>("UserId1")
                        .HasColumnType("int");

                    b.HasKey("UserId", "RoleId");

                    b.HasIndex("RoleId");

                    b.HasIndex("RoleId1");

                    b.HasIndex("UserId1");

                    b.ToTable("AspNetUserRoles");
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>", b =>
                {
                    b.Property<int>("Id")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("int");

                    b.Property<string>("ClaimType")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<string>("ClaimValue")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<int>("RoleId")
                        .HasColumnType("int");

                    b.HasKey("Id");

                    b.HasIndex("RoleId");

                    b.ToTable("AspNetRoleClaims");
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<int>", b =>
                {
                    b.Property<int>("Id")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("int");

                    b.Property<string>("ClaimType")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<string>("ClaimValue")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<int>("UserId")
                        .HasColumnType("int");

                    b.HasKey("Id");

                    b.HasIndex("UserId");

                    b.ToTable("AspNetUserClaims");
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<int>", b =>
                {
                    b.Property<string>("LoginProvider")
                        .HasColumnType("varchar(255) CHARACTER SET utf8mb4");

                    b.Property<string>("ProviderKey")
                        .HasColumnType("varchar(255) CHARACTER SET utf8mb4");

                    b.Property<string>("ProviderDisplayName")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<int>("UserId")
                        .HasColumnType("int");

                    b.HasKey("LoginProvider", "ProviderKey");

                    b.HasIndex("UserId");

                    b.ToTable("AspNetUserLogins");
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<int>", b =>
                {
                    b.Property<int>("UserId")
                        .HasColumnType("int");

                    b.Property<string>("LoginProvider")
                        .HasColumnType("varchar(255) CHARACTER SET utf8mb4");

                    b.Property<string>("Name")
                        .HasColumnType("varchar(255) CHARACTER SET utf8mb4");

                    b.Property<string>("Value")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.HasKey("UserId", "LoginProvider", "Name");

                    b.ToTable("AspNetUserTokens");
                });

            modelBuilder.Entity("Blog.IdentityServer.Models.ApplicationUserRole", b =>
                {
                    b.HasOne("Blog.IdentityServer.Models.ApplicationRole", null)
                        .WithMany()
                        .HasForeignKey("RoleId")
                        .OnDelete(DeleteBehavior.Cascade)
                        .IsRequired();

                    b.HasOne("Blog.IdentityServer.Models.ApplicationRole", "Role")
                        .WithMany("UserRoles")
                        .HasForeignKey("RoleId1");

                    b.HasOne("Blog.IdentityServer.Models.ApplicationUser", null)
                        .WithMany()
                        .HasForeignKey("UserId")
                        .OnDelete(DeleteBehavior.Cascade)
                        .IsRequired();

                    b.HasOne("Blog.IdentityServer.Models.ApplicationUser", "User")
                        .WithMany("UserRoles")
                        .HasForeignKey("UserId1");
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>", b =>
                {
                    b.HasOne("Blog.IdentityServer.Models.ApplicationRole", null)
                        .WithMany()
                        .HasForeignKey("RoleId")
                        .OnDelete(DeleteBehavior.Cascade)
                        .IsRequired();
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<int>", b =>
                {
                    b.HasOne("Blog.IdentityServer.Models.ApplicationUser", null)
                        .WithMany()
                        .HasForeignKey("UserId")
                        .OnDelete(DeleteBehavior.Cascade)
                        .IsRequired();
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<int>", b =>
                {
                    b.HasOne("Blog.IdentityServer.Models.ApplicationUser", null)
                        .WithMany()
                        .HasForeignKey("UserId")
                        .OnDelete(DeleteBehavior.Cascade)
                        .IsRequired();
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<int>", b =>
                {
                    b.HasOne("Blog.IdentityServer.Models.ApplicationUser", null)
                        .WithMany()
                        .HasForeignKey("UserId")
                        .OnDelete(DeleteBehavior.Cascade)
                        .IsRequired();
                });
#pragma warning restore 612, 618
        }
    }
}


================================================
FILE: Blog.IdentityServer/Data/MigrationsMySql/20200509165505_AppDbMigration.cs
================================================
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;

namespace Blog.IdentityServer.Data.MigrationsMySql
{
    public partial class AppDbMigration : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: "AspNetRoles",
                columns: table => new
                {
                    Id = table.Column<int>(nullable: false)
                        .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
                    Name = table.Column<string>(maxLength: 256, nullable: true),
                    NormalizedName = table.Column<string>(maxLength: 256, nullable: true),
                    ConcurrencyStamp = table.Column<string>(nullable: true),
                    IsDeleted = table.Column<bool>(nullable: false),
                    Description = table.Column<string>(nullable: true),
                    OrderSort = table.Column<int>(nullable: false),
                    Enabled = table.Column<bool>(nullable: false),
                    CreateId = table.Column<int>(nullable: true),
                    CreateBy = table.Column<string>(nullable: true),
                    CreateTime = table.Column<DateTime>(nullable: true),
                    ModifyId = table.Column<int>(nullable: true),
                    ModifyBy = table.Column<string>(nullable: true),
                    ModifyTime = table.Column<DateTime>(nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_AspNetRoles", x => x.Id);
                });

            migrationBuilder.CreateTable(
                name: "AspNetUsers",
                columns: table => new
                {
                    Id = table.Column<int>(nullable: false)
                        .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
                    UserName = table.Column<string>(maxLength: 256, nullable: true),
                    NormalizedUserName = table.Column<string>(maxLength: 256, nullable: true),
                    Email = table.Column<string>(maxLength: 256, nullable: true),
                    NormalizedEmail = table.Column<string>(maxLength: 256, nullable: true),
                    EmailConfirmed = table.Column<bool>(nullable: false),
                    PasswordHash = table.Column<string>(nullable: true),
                    SecurityStamp = table.Column<string>(nullable: true),
                    ConcurrencyStamp = table.Column<string>(nullable: true),
                    PhoneNumber = table.Column<string>(nullable: true),
                    PhoneNumberConfirmed = table.Column<bool>(nullable: false),
                    TwoFactorEnabled = table.Column<bool>(nullable: false),
                    LockoutEnd = table.Column<DateTimeOffset>(nullable: true),
                    LockoutEnabled = table.Column<bool>(nullable: false),
                    AccessFailedCount = table.Column<int>(nullable: false),
                    LoginName = table.Column<string>(nullable: true),
                    RealName = table.Column<string>(nullable: true),
                    sex = table.Column<int>(nullable: false),
                    age = table.Column<int>(nullable: false),
                    birth = table.Column<DateTime>(nullable: false),
                    addr = table.Column<string>(nullable: true),
                    tdIsDelete = table.Column<bool>(nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_AspNetUsers", x => x.Id);
                });

            migrationBuilder.CreateTable(
                name: "AspNetRoleClaims",
                columns: table => new
                {
                    Id = table.Column<int>(nullable: false)
                        .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
                    RoleId = table.Column<int>(nullable: false),
                    ClaimType = table.Column<string>(nullable: true),
                    ClaimValue = table.Column<string>(nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
                    table.ForeignKey(
                        name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
                        column: x => x.RoleId,
                        principalTable: "AspNetRoles",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Cascade);
                });

            migrationBuilder.CreateTable(
                name: "AspNetUserClaims",
                columns: table => new
                {
                    Id = table.Column<int>(nullable: false)
                        .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
                    UserId = table.Column<int>(nullable: false),
                    ClaimType = table.Column<string>(nullable: true),
                    ClaimValue = table.Column<string>(nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
                    table.ForeignKey(
                        name: "FK_AspNetUserClaims_AspNetUsers_UserId",
                        column: x => x.UserId,
                        principalTable: "AspNetUsers",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Cascade);
                });

            migrationBuilder.CreateTable(
                name: "AspNetUserLogins",
                columns: table => new
                {
                    LoginProvider = table.Column<string>(nullable: false),
                    ProviderKey = table.Column<string>(nullable: false),
                    ProviderDisplayName = table.Column<string>(nullable: true),
                    UserId = table.Column<int>(nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
                    table.ForeignKey(
                        name: "FK_AspNetUserLogins_AspNetUsers_UserId",
                        column: x => x.UserId,
                        principalTable: "AspNetUsers",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Cascade);
                });

            migrationBuilder.CreateTable(
                name: "AspNetUserRoles",
                columns: table => new
                {
                    UserId = table.Column<int>(nullable: false),
                    RoleId = table.Column<int>(nullable: false),
                    UserId1 = table.Column<int>(nullable: true),
                    RoleId1 = table.Column<int>(nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
                    table.ForeignKey(
                        name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
                        column: x => x.RoleId,
                        principalTable: "AspNetRoles",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Cascade);
                    table.ForeignKey(
                        name: "FK_AspNetUserRoles_AspNetRoles_RoleId1",
                        column: x => x.RoleId1,
                        principalTable: "AspNetRoles",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                    table.ForeignKey(
                        name: "FK_AspNetUserRoles_AspNetUsers_UserId",
                        column: x => x.UserId,
                        principalTable: "AspNetUsers",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Cascade);
                    table.ForeignKey(
                        name: "FK_AspNetUserRoles_AspNetUsers_UserId1",
                        column: x => x.UserId1,
                        principalTable: "AspNetUsers",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                });

            migrationBuilder.CreateTable(
                name: "AspNetUserTokens",
                columns: table => new
                {
                    UserId = table.Column<int>(nullable: false),
                    LoginProvider = table.Column<string>(nullable: false),
                    Name = table.Column<string>(nullable: false),
                    Value = table.Column<string>(nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
                    table.ForeignKey(
                        name: "FK_AspNetUserTokens_AspNetUsers_UserId",
                        column: x => x.UserId,
                        principalTable: "AspNetUsers",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Cascade);
                });

            migrationBuilder.CreateIndex(
                name: "IX_AspNetRoleClaims_RoleId",
                table: "AspNetRoleClaims",
                column: "RoleId");

            migrationBuilder.CreateIndex(
                name: "RoleNameIndex",
                table: "AspNetRoles",
                column: "NormalizedName",
                unique: true);

            migrationBuilder.CreateIndex(
                name: "IX_AspNetUserClaims_UserId",
                table: "AspNetUserClaims",
                column: "UserId");

            migrationBuilder.CreateIndex(
                name: "IX_AspNetUserLogins_UserId",
                table: "AspNetUserLogins",
                column: "UserId");

            migrationBuilder.CreateIndex(
                name: "IX_AspNetUserRoles_RoleId",
                table: "AspNetUserRoles",
                column: "RoleId");

            migrationBuilder.CreateIndex(
                name: "IX_AspNetUserRoles_RoleId1",
                table: "AspNetUserRoles",
                column: "RoleId1");

            migrationBuilder.CreateIndex(
                name: "IX_AspNetUserRoles_UserId1",
                table: "AspNetUserRoles",
                column: "UserId1");

            migrationBuilder.CreateIndex(
                name: "EmailIndex",
                table: "AspNetUsers",
                column: "NormalizedEmail");

            migrationBuilder.CreateIndex(
                name: "UserNameIndex",
                table: "AspNetUsers",
                column: "NormalizedUserName",
                unique: true);
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropTable(
                name: "AspNetRoleClaims");

            migrationBuilder.DropTable(
                name: "AspNetUserClaims");

            migrationBuilder.DropTable(
                name: "AspNetUserLogins");

            migrationBuilder.DropTable(
                name: "AspNetUserRoles");

            migrationBuilder.DropTable(
                name: "AspNetUserTokens");

            migrationBuilder.DropTable(
                name: "AspNetRoles");

            migrationBuilder.DropTable(
                name: "AspNetUsers");
        }
    }
}


================================================
FILE: Blog.IdentityServer/Data/MigrationsMySql/20210808045732_addQuestion.Designer.cs
================================================
// <auto-generated />
using System;
using Blog.IdentityServer.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;

namespace Blog.IdentityServer.Data.MigrationsMySql
{
    [DbContext(typeof(ApplicationDbContext))]
    [Migration("20210808045732_addQuestion")]
    partial class addQuestion
    {
        protected override void BuildTargetModel(ModelBuilder modelBuilder)
        {
#pragma warning disable 612, 618
            modelBuilder
                .HasAnnotation("ProductVersion", "3.1.5")
                .HasAnnotation("Relational:MaxIdentifierLength", 64);

            modelBuilder.Entity("Blog.IdentityServer.Models.ApplicationRole", b =>
                {
                    b.Property<int>("Id")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("int");

                    b.Property<string>("ConcurrencyStamp")
                        .IsConcurrencyToken()
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<string>("CreateBy")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<int?>("CreateId")
                        .HasColumnType("int");

                    b.Property<DateTime?>("CreateTime")
                        .HasColumnType("datetime(6)");

                    b.Property<string>("Description")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<bool>("Enabled")
                        .HasColumnType("tinyint(1)");

                    b.Property<bool>("IsDeleted")
                        .HasColumnType("tinyint(1)");

                    b.Property<string>("ModifyBy")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<int?>("ModifyId")
                        .HasColumnType("int");

                    b.Property<DateTime?>("ModifyTime")
                        .HasColumnType("datetime(6)");

                    b.Property<string>("Name")
                        .HasColumnType("varchar(256) CHARACTER SET utf8mb4")
                        .HasMaxLength(256);

                    b.Property<string>("NormalizedName")
                        .HasColumnType("varchar(256) CHARACTER SET utf8mb4")
                        .HasMaxLength(256);

                    b.Property<int>("OrderSort")
                        .HasColumnType("int");

                    b.HasKey("Id");

                    b.HasIndex("NormalizedName")
                        .IsUnique()
                        .HasName("RoleNameIndex");

                    b.ToTable("AspNetRoles");
                });

            modelBuilder.Entity("Blog.IdentityServer.Models.ApplicationUser", b =>
                {
                    b.Property<int>("Id")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("int");

                    b.Property<int>("AccessFailedCount")
                        .HasColumnType("int");

                    b.Property<string>("ConcurrencyStamp")
                        .IsConcurrencyToken()
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<string>("Email")
                        .HasColumnType("varchar(256) CHARACTER SET utf8mb4")
                        .HasMaxLength(256);

                    b.Property<bool>("EmailConfirmed")
                        .HasColumnType("tinyint(1)");

                    b.Property<string>("FirstQuestion")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<bool>("LockoutEnabled")
                        .HasColumnType("tinyint(1)");

                    b.Property<DateTimeOffset?>("LockoutEnd")
                        .HasColumnType("datetime(6)");

                    b.Property<string>("LoginName")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<string>("NormalizedEmail")
                        .HasColumnType("varchar(256) CHARACTER SET utf8mb4")
                        .HasMaxLength(256);

                    b.Property<string>("NormalizedUserName")
                        .HasColumnType("varchar(256) CHARACTER SET utf8mb4")
                        .HasMaxLength(256);

                    b.Property<string>("PasswordHash")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<string>("PhoneNumber")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<bool>("PhoneNumberConfirmed")
                        .HasColumnType("tinyint(1)");

                    b.Property<string>("RealName")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<string>("SecondQuestion")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<string>("SecurityStamp")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<bool>("TwoFactorEnabled")
                        .HasColumnType("tinyint(1)");

                    b.Property<string>("UserName")
                        .HasColumnType("varchar(256) CHARACTER SET utf8mb4")
                        .HasMaxLength(256);

                    b.Property<string>("addr")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<int>("age")
                        .HasColumnType("int");

                    b.Property<DateTime>("birth")
                        .HasColumnType("datetime(6)");

                    b.Property<int>("sex")
                        .HasColumnType("int");

                    b.Property<bool>("tdIsDelete")
                        .HasColumnType("tinyint(1)");

                    b.HasKey("Id");

                    b.HasIndex("NormalizedEmail")
                        .HasName("EmailIndex");

                    b.HasIndex("NormalizedUserName")
                        .IsUnique()
                        .HasName("UserNameIndex");

                    b.ToTable("AspNetUsers");
                });

            modelBuilder.Entity("Blog.IdentityServer.Models.ApplicationUserRole", b =>
                {
                    b.Property<int>("UserId")
                        .HasColumnType("int");

                    b.Property<int>("RoleId")
                        .HasColumnType("int");

                    b.Property<int?>("RoleId1")
                        .HasColumnType("int");

                    b.Property<int?>("UserId1")
                        .HasColumnType("int");

                    b.HasKey("UserId", "RoleId");

                    b.HasIndex("RoleId");

                    b.HasIndex("RoleId1");

                    b.HasIndex("UserId1");

                    b.ToTable("AspNetUserRoles");
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>", b =>
                {
                    b.Property<int>("Id")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("int");

                    b.Property<string>("ClaimType")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<string>("ClaimValue")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<int>("RoleId")
                        .HasColumnType("int");

                    b.HasKey("Id");

                    b.HasIndex("RoleId");

                    b.ToTable("AspNetRoleClaims");
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<int>", b =>
                {
                    b.Property<int>("Id")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("int");

                    b.Property<string>("ClaimType")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<string>("ClaimValue")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<int>("UserId")
                        .HasColumnType("int");

                    b.HasKey("Id");

                    b.HasIndex("UserId");

                    b.ToTable("AspNetUserClaims");
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<int>", b =>
                {
                    b.Property<string>("LoginProvider")
                        .HasColumnType("varchar(255) CHARACTER SET utf8mb4");

                    b.Property<string>("ProviderKey")
                        .HasColumnType("varchar(255) CHARACTER SET utf8mb4");

                    b.Property<string>("ProviderDisplayName")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.Property<int>("UserId")
                        .HasColumnType("int");

                    b.HasKey("LoginProvider", "ProviderKey");

                    b.HasIndex("UserId");

                    b.ToTable("AspNetUserLogins");
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<int>", b =>
                {
                    b.Property<int>("UserId")
                        .HasColumnType("int");

                    b.Property<string>("LoginProvider")
                        .HasColumnType("varchar(255) CHARACTER SET utf8mb4");

                    b.Property<string>("Name")
                        .HasColumnType("varchar(255) CHARACTER SET utf8mb4");

                    b.Property<string>("Value")
                        .HasColumnType("longtext CHARACTER SET utf8mb4");

                    b.HasKey("UserId", "LoginProvider", "Name");

                    b.ToTable("AspNetUserTokens");
                });

            modelBuilder.Entity("Blog.IdentityServer.Models.ApplicationUserRole", b =>
                {
                    b.HasOne("Blog.IdentityServer.Models.ApplicationRole", null)
                        .WithMany()
                        .HasForeignKey("RoleId")
                        .OnDelete(DeleteBehavior.Cascade)
                        .IsRequired();

                    b.HasOne("Blog.IdentityServer.Models.ApplicationRole", "Role")
                        .WithMany("UserRoles")
                        .HasForeignKey("RoleId1");

                    b.HasOne("Blog.IdentityServer.Models.ApplicationUser", null)
                        .WithMany()
                        .HasForeignKey("UserId")
                        .OnDelete(DeleteBehavior.Cascade)
                        .IsRequired();

                    b.HasOne("Blog.IdentityServer.Models.ApplicationUser", "User")
                        .WithMany("UserRoles")
                        .HasForeignKey("UserId1");
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>", b =>
                {
                    b.HasOne("Blog.IdentityServer.Models.ApplicationRole", null)
                        .WithMany()
                        .HasForeignKey("RoleId")
                        .OnDelete(DeleteBehavior.Cascade)
                        .IsRequired();
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<int>", b =>
                {
                    b.HasOne("Blog.IdentityServer.Models.ApplicationUser", null)
                        .WithMany()
                        .HasForeignKey("UserId")
                        .OnDelete(DeleteBehavior.Cascade)
                        .IsRequired();
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<int>", b =>
                {
                    b.HasOne("Blog.IdentityServer.Models.ApplicationUser", null)
                        .WithMany()
                        .HasForeignKey("UserId")
                        .OnDelete(DeleteBehavior.Cascade)
                        .IsRequired();
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<int>", b =>
                {
                    b.HasOne("Blog.IdentityServer.Models.ApplicationUser", null)
                        .WithMany()
                        .HasForeignKey("UserId")
                        .OnDelete(DeleteBehavior.Cascade)
                        .IsRequired();
                });
#pragma warning restore 612, 618
        }
    }
}


================================================
FILE: Blog.IdentityServer/Data/MigrationsMySql/20210808045732_addQuestion.cs
================================================
using Microsoft.EntityFrameworkCore.Migrations;

namespace Blog.IdentityServer.Data.MigrationsMySql
{
    public partial class addQuestion : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.AddColumn<string>(
                name: "FirstQuestion",
                table: "AspNetUsers",
                nullable: true);

            migrationBuilder.AddColumn<string>(
                name: "SecondQuestion",
                table: "AspNetUsers",
                nullable: true);
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropColumn(
                name: "FirstQuestion",
                table: "AspNetUsers");

            migrationBuilder.DropColumn(
                name: "SecondQuestion",
                table: "AspNetUsers");
        }
    }
}


================================================
FILE: Blog.IdentityServer/Data/MigrationsMySql/ApplicationDbContextModelSnapshot.cs
================================================
// <auto-generated />
using System;
using Blog.IdentityServer.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;

namespace Blog.IdentityServer.Data.MigrationsMySql
{
    [DbContext(typeof(ApplicationDbContext))]
    partial class ApplicationDbContextModelSnapshot : ModelSnapshot
    {
        protected override void BuildModel(ModelBuilder modelBuilder)
        {
#pragma warning disable 612, 618
            modelBuilder
                .HasAnnotation("ProductVersion", "3.1.5")
                .HasAnnotation("Relational:MaxIdentifierLength", 64);

            modelBuilder.Entity("Blog.IdentityServer.Models.App
Download .txt
gitextract_athlf9j7/

├── .dockerignore
├── .gitattributes
├── .gitignore
├── Blog.IdentityServer/
│   ├── Authorization/
│   │   ├── ClaimRequirement.cs
│   │   └── ClaimsRequirementHandler.cs
│   ├── Blog.IdentityServer.csproj
│   ├── Config.cs
│   ├── Controllers/
│   │   ├── Account/
│   │   │   ├── AccountController.cs
│   │   │   ├── AccountOptions.cs
│   │   │   ├── EditViewModel.cs
│   │   │   ├── ExternalController.cs
│   │   │   ├── ExternalProvider.cs
│   │   │   ├── ForgotPasswordViewModel.cs
│   │   │   ├── LoggedOutViewModel.cs
│   │   │   ├── LoginInputModel.cs
│   │   │   ├── LoginViewModel.cs
│   │   │   ├── LogoutInputModel.cs
│   │   │   ├── LogoutViewModel.cs
│   │   │   ├── RedirectViewModel.cs
│   │   │   ├── RegisterViewModel.cs
│   │   │   ├── ResetPasswordViewModel.cs
│   │   │   ├── RoleEditViewModel.cs
│   │   │   ├── RoleRegisterViewModel.cs
│   │   │   └── UrlHelperExtensions.cs
│   │   ├── ApiResource/
│   │   │   ├── ApiResourceDto.cs
│   │   │   └── ApiResourcesManager.cs
│   │   ├── Client/
│   │   │   ├── ClientDto.cs
│   │   │   └── ClientsManagerController.cs
│   │   ├── Consent/
│   │   │   ├── ConsentController.cs
│   │   │   ├── ConsentInputModel.cs
│   │   │   ├── ConsentOptions.cs
│   │   │   ├── ConsentViewModel.cs
│   │   │   ├── ProcessConsentResult.cs
│   │   │   └── ScopeViewModel.cs
│   │   ├── Device/
│   │   │   ├── DeviceAuthorizationInputModel.cs
│   │   │   ├── DeviceAuthorizationViewModel.cs
│   │   │   └── DeviceController.cs
│   │   ├── Diagnostics/
│   │   │   ├── DiagnosticsController.cs
│   │   │   └── DiagnosticsViewModel.cs
│   │   ├── Extensions.cs
│   │   ├── Grants/
│   │   │   ├── GrantsController.cs
│   │   │   └── GrantsViewModel.cs
│   │   ├── Home/
│   │   │   ├── ErrorViewModel.cs
│   │   │   ├── HomeController.cs
│   │   │   └── Is4ApiController.cs
│   │   ├── SecurityHeadersAttribute.cs
│   │   └── TestUsers.cs
│   ├── Data/
│   │   ├── ApplicationDbContext.cs
│   │   └── MigrationsMySql/
│   │       ├── 20200509165505_AppDbMigration.Designer.cs
│   │       ├── 20200509165505_AppDbMigration.cs
│   │       ├── 20210808045732_addQuestion.Designer.cs
│   │       ├── 20210808045732_addQuestion.cs
│   │       ├── ApplicationDbContextModelSnapshot.cs
│   │       └── IdentityServer/
│   │           ├── ConfigurationDb/
│   │           │   ├── 20200509165153_InitialIdentityServerConfigurationDbMigrationMysql.Designer.cs
│   │           │   ├── 20200509165153_InitialIdentityServerConfigurationDbMigrationMysql.cs
│   │           │   ├── 20200715033226_InitConfigurationDbV4.Designer.cs
│   │           │   ├── 20200715033226_InitConfigurationDbV4.cs
│   │           │   └── ConfigurationDbContextModelSnapshot.cs
│   │           └── PersistedGrantDb/
│   │               ├── 20200509165052_InitialIdentityServerPersistedGrantDbMigrationMysql.Designer.cs
│   │               ├── 20200509165052_InitialIdentityServerPersistedGrantDbMigrationMysql.cs
│   │               ├── 20200715032957_InitPersistedGrantDbV4.Designer.cs
│   │               ├── 20200715032957_InitPersistedGrantDbV4.cs
│   │               └── PersistedGrantDbContextModelSnapshot.cs
│   ├── Dockerfile
│   ├── Extensions/
│   │   ├── GrantTypeCustom.cs
│   │   ├── IpLimitMildd.cs
│   │   ├── IpPolicyRateLimitSetup.cs
│   │   ├── ResourceOwnerPasswordValidator.cs
│   │   └── WeiXinOpenGrantValidator.cs
│   ├── Helper/
│   │   ├── Appsettings.cs
│   │   ├── FileHelper.cs
│   │   ├── GetNetData.cs
│   │   ├── HtmlHelper.cs
│   │   ├── JsonHelper.cs
│   │   ├── MD5Hepler.cs
│   │   ├── RecursionHelper.cs
│   │   ├── SerializeHelper.cs
│   │   ├── UnicodeHelper.cs
│   │   └── UtilConvert.cs
│   ├── InMemoryConfig.cs
│   ├── LICENSE
│   ├── Models/
│   │   ├── ApplicationRole.cs
│   │   ├── ApplicationUser.cs
│   │   ├── ApplicationUserRole.cs
│   │   ├── Bak/
│   │   │   ├── Role.cs
│   │   │   ├── RootEntity.cs
│   │   │   ├── UserRole.cs
│   │   │   └── sysUserInfo.cs
│   │   ├── Dtos/
│   │   │   └── MessageModel.cs
│   │   └── ViewModel/
│   │       └── AccessApiDateView.cs
│   ├── Program.cs
│   ├── Properties/
│   │   ├── PublishProfiles/
│   │   │   └── FolderProfile.pubxml
│   │   └── launchSettings.json
│   ├── SameSiteHandlingExtensions.cs
│   ├── SeedData.cs
│   ├── Startup.cs
│   ├── Views/
│   │   ├── Account/
│   │   │   ├── AccessDenied.cshtml
│   │   │   ├── ConfirmEmail.cshtml
│   │   │   ├── Edit.cshtml
│   │   │   ├── ForgotPassword.cshtml
│   │   │   ├── ForgotPasswordConfirmation.cshtml
│   │   │   ├── LoggedOut.cshtml
│   │   │   ├── Login.cshtml
│   │   │   ├── Logout.cshtml
│   │   │   ├── My.cshtml
│   │   │   ├── Register.cshtml
│   │   │   ├── ResetPassword.cshtml
│   │   │   ├── ResetPasswordConfirmation.cshtml
│   │   │   ├── RoleEdit.cshtml
│   │   │   ├── RoleRegister.cshtml
│   │   │   ├── Roles.cshtml
│   │   │   └── Users.cshtml
│   │   ├── ApiResourcesManager/
│   │   │   ├── CreateOrEdit.cshtml
│   │   │   └── Index.cshtml
│   │   ├── ClientsManager/
│   │   │   ├── CreateOrEdit.cshtml
│   │   │   └── Index.cshtml
│   │   ├── Consent/
│   │   │   └── Index.cshtml
│   │   ├── Device/
│   │   │   ├── Success.cshtml
│   │   │   ├── UserCodeCapture.cshtml
│   │   │   └── UserCodeConfirmation.cshtml
│   │   ├── Diagnostics/
│   │   │   └── Index.cshtml
│   │   ├── Grants/
│   │   │   ├── Config.cshtml
│   │   │   └── Index.cshtml
│   │   ├── Home/
│   │   │   └── Index.cshtml
│   │   ├── Shared/
│   │   │   ├── Error.cshtml
│   │   │   ├── Redirect.cshtml
│   │   │   ├── _Layout.cshtml
│   │   │   ├── _ScopeListItem.cshtml
│   │   │   └── _ValidationSummary.cshtml
│   │   ├── _ViewImports.cshtml
│   │   └── _ViewStart.cshtml
│   ├── appsettings.Development.json
│   ├── appsettings.json
│   ├── tempkey.jwk
│   ├── tempkey.rsa
│   └── wwwroot/
│       ├── css/
│       │   ├── login_styles.css
│       │   ├── showtip.css
│       │   ├── site.css
│       │   ├── site.less
│       │   └── web.css
│       ├── fonts/
│       │   ├── FontAwesome.otf
│       │   └── open-iconic.otf
│       ├── js/
│       │   ├── Role.js
│       │   ├── User.js
│       │   ├── bootstrap-show-password.js
│       │   ├── showTip.js
│       │   ├── signin-redirect.js
│       │   └── signout-redirect.js
│       └── lib/
│           ├── bootstrap/
│           │   ├── css/
│           │   │   └── bootstrap.css
│           │   └── js/
│           │       └── bootstrap.js
│           ├── jquery-validation/
│           │   ├── .bower.json
│           │   ├── CONTRIBUTING.md
│           │   ├── Gruntfile.js
│           │   ├── LICENSE.md
│           │   ├── README.md
│           │   ├── bower.json
│           │   ├── changelog.md
│           │   ├── dist/
│           │   │   ├── additional-methods.js
│           │   │   └── jquery.validate.js
│           │   ├── package.json
│           │   ├── src/
│           │   │   ├── additional/
│           │   │   │   ├── accept.js
│           │   │   │   ├── additional.js
│           │   │   │   ├── alphanumeric.js
│           │   │   │   ├── bankaccountNL.js
│           │   │   │   ├── bankorgiroaccountNL.js
│           │   │   │   ├── bic.js
│           │   │   │   ├── cifES.js
│           │   │   │   ├── cpfBR.js
│           │   │   │   ├── creditcardtypes.js
│           │   │   │   ├── currency.js
│           │   │   │   ├── dateFA.js
│           │   │   │   ├── dateITA.js
│           │   │   │   ├── dateNL.js
│           │   │   │   ├── extension.js
│           │   │   │   ├── giroaccountNL.js
│           │   │   │   ├── iban.js
│           │   │   │   ├── integer.js
│           │   │   │   ├── ipv4.js
│           │   │   │   ├── ipv6.js
│           │   │   │   ├── lettersonly.js
│           │   │   │   ├── letterswithbasicpunc.js
│           │   │   │   ├── mobileNL.js
│           │   │   │   ├── mobileUK.js
│           │   │   │   ├── nieES.js
│           │   │   │   ├── nifES.js
│           │   │   │   ├── notEqualTo.js
│           │   │   │   ├── nowhitespace.js
│           │   │   │   ├── pattern.js
│           │   │   │   ├── phoneNL.js
│           │   │   │   ├── phoneUK.js
│           │   │   │   ├── phoneUS.js
│           │   │   │   ├── phonesUK.js
│           │   │   │   ├── postalCodeCA.js
│           │   │   │   ├── postalcodeBR.js
│           │   │   │   ├── postalcodeIT.js
│           │   │   │   ├── postalcodeNL.js
│           │   │   │   ├── postcodeUK.js
│           │   │   │   ├── require_from_group.js
│           │   │   │   ├── skip_or_fill_minimum.js
│           │   │   │   ├── statesUS.js
│           │   │   │   ├── strippedminlength.js
│           │   │   │   ├── time.js
│           │   │   │   ├── time12h.js
│           │   │   │   ├── url2.js
│           │   │   │   ├── vinUS.js
│           │   │   │   ├── zipcodeUS.js
│           │   │   │   └── ziprange.js
│           │   │   ├── ajax.js
│           │   │   ├── core.js
│           │   │   └── localization/
│           │   │       ├── messages_ar.js
│           │   │       ├── messages_bg.js
│           │   │       ├── messages_bn_BD.js
│           │   │       ├── messages_ca.js
│           │   │       ├── messages_cs.js
│           │   │       ├── messages_da.js
│           │   │       ├── messages_de.js
│           │   │       ├── messages_el.js
│           │   │       ├── messages_es.js
│           │   │       ├── messages_es_AR.js
│           │   │       ├── messages_es_PE.js
│           │   │       ├── messages_et.js
│           │   │       ├── messages_eu.js
│           │   │       ├── messages_fa.js
│           │   │       ├── messages_fi.js
│           │   │       ├── messages_fr.js
│           │   │       ├── messages_ge.js
│           │   │       ├── messages_gl.js
│           │   │       ├── messages_he.js
│           │   │       ├── messages_hr.js
│           │   │       ├── messages_hu.js
│           │   │       ├── messages_hy_AM.js
│           │   │       ├── messages_id.js
│           │   │       ├── messages_is.js
│           │   │       ├── messages_it.js
│           │   │       ├── messages_ja.js
│           │   │       ├── messages_ka.js
│           │   │       ├── messages_kk.js
│           │   │       ├── messages_ko.js
│           │   │       ├── messages_lt.js
│           │   │       ├── messages_lv.js
│           │   │       ├── messages_my.js
│           │   │       ├── messages_nl.js
│           │   │       ├── messages_no.js
│           │   │       ├── messages_pl.js
│           │   │       ├── messages_pt_BR.js
│           │   │       ├── messages_pt_PT.js
│           │   │       ├── messages_ro.js
│           │   │       ├── messages_ru.js
│           │   │       ├── messages_si.js
│           │   │       ├── messages_sk.js
│           │   │       ├── messages_sl.js
│           │   │       ├── messages_sr.js
│           │   │       ├── messages_sr_lat.js
│           │   │       ├── messages_sv.js
│           │   │       ├── messages_th.js
│           │   │       ├── messages_tj.js
│           │   │       ├── messages_tr.js
│           │   │       ├── messages_uk.js
│           │   │       ├── messages_vi.js
│           │   │       ├── messages_zh.js
│           │   │       ├── messages_zh_TW.js
│           │   │       ├── methods_de.js
│           │   │       ├── methods_es_CL.js
│           │   │       ├── methods_fi.js
│           │   │       ├── methods_nl.js
│           │   │       └── methods_pt.js
│           │   └── validation.jquery.json
│           └── jquery-validation-unobtrusive/
│               ├── .bower.json
│               ├── LICENSE.txt
│               ├── bower.json
│               └── jquery.validate.unobtrusive.js
├── Blog.IdentityServer.Publish.Docker.sh
├── Blog.IdentityServer.Publish.Linux.sh
├── Blog.IdentityServer.sln
├── Build.bat
├── Dockerfile
└── README.md
Download .txt
SYMBOL INDEX (330 symbols across 95 files)

FILE: Blog.IdentityServer/Authorization/ClaimRequirement.cs
  class ClaimRequirement (line 5) | public class ClaimRequirement : IAuthorizationRequirement
    method ClaimRequirement (line 7) | public ClaimRequirement(string claimName, string claimValue)

FILE: Blog.IdentityServer/Authorization/ClaimsRequirementHandler.cs
  class ClaimsRequirementHandler (line 7) | public class ClaimsRequirementHandler : AuthorizationHandler<ClaimRequir...
    method HandleRequirementAsync (line 10) | protected override Task HandleRequirementAsync(AuthorizationHandlerCon...

FILE: Blog.IdentityServer/Config.cs
  class Config (line 13) | public class Config
    method GetIdentityResources (line 16) | public static IEnumerable<IdentityResource> GetIdentityResources()
    method GetApiScopes (line 29) | public static IEnumerable<ApiScope> GetApiScopes()
    method GetApiResources (line 37) | public static IEnumerable<ApiResource> GetApiResources()
    method GetClients (line 58) | public static IEnumerable<Client> GetClients()

FILE: Blog.IdentityServer/Controllers/Account/AccountController.cs
  class AccountController (line 27) | [SecurityHeaders]
    method AccountController (line 38) | public AccountController(
    method Login (line 59) | [HttpGet]
    method Login (line 78) | [HttpPost]
    method ExternalLogin (line 165) | [HttpGet]
    method ExternalLoginCallback (line 192) | [HttpGet]
    method Logout (line 257) | [HttpGet]
    method Logout (line 276) | [HttpPost]
    method BuildLoginViewModelAsync (line 310) | private async Task<LoginViewModel> BuildLoginViewModelAsync(string ret...
    method BuildLoginViewModelAsync (line 362) | private async Task<LoginViewModel> BuildLoginViewModelAsync(LoginInput...
    method BuildLogoutViewModelAsync (line 370) | private async Task<LogoutViewModel> BuildLogoutViewModelAsync(string l...
    method BuildLoggedOutViewModelAsync (line 394) | private async Task<LoggedOutViewModel> BuildLoggedOutViewModelAsync(st...
    method ProcessWindowsLoginAsync (line 432) | private async Task<IActionResult> ProcessWindowsLoginAsync(string retu...
    method FindUserFromExternalProviderAsync (line 479) | private async Task<(ApplicationUser user, string provider, string prov...
    method AutoProvisionUserAsync (line 504) | private async Task<ApplicationUser> AutoProvisionUserAsync(string prov...
    method ProcessLoginCallbackForOidc (line 563) | private void ProcessLoginCallbackForOidc(AuthenticateResult externalRe...
    method ProcessLoginCallbackForWsFed (line 581) | private void ProcessLoginCallbackForWsFed(AuthenticateResult externalR...
    method ProcessLoginCallbackForSaml2p (line 585) | private void ProcessLoginCallbackForSaml2p(AuthenticateResult external...
    method Register (line 592) | [HttpGet]
    method Register (line 600) | [HttpPost]
    method Users (line 679) | [HttpGet]
    method Edit (line 692) | [HttpGet("{id}")]
    method Edit (line 714) | [HttpPost]
    method My (line 790) | [HttpGet]
    method My (line 813) | [HttpPost]
    method Delete (line 905) | [HttpPost]
    method ConfirmEmail (line 941) | [HttpGet]
    method ForgotPassword (line 959) | [HttpGet]
    method ForgotPassword (line 967) | [HttpPost]
    method ForgotPasswordConfirmation (line 1028) | [HttpGet]
    method ResetPassword (line 1037) | [HttpGet]
    method ResetPassword (line 1050) | [HttpPost]
    method ResetPasswordConfirmation (line 1091) | [HttpGet]
    method AccessDenied (line 1100) | [HttpGet]
    method AddErrors (line 1108) | private void AddErrors(IdentityResult result)
    method RedirectToLocal (line 1116) | private IActionResult RedirectToLocal(string returnUrl)
    method RoleRegister (line 1133) | [HttpGet]
    method RoleRegister (line 1141) | [HttpPost]
    method Roles (line 1191) | [HttpGet]
    method RoleEdit (line 1204) | [HttpGet("{id}")]
    method RoleEdit (line 1226) | [HttpPost]
    method RoleDelete (line 1266) | [HttpPost]

FILE: Blog.IdentityServer/Controllers/Account/AccountOptions.cs
  class AccountOptions (line 9) | public class AccountOptions

FILE: Blog.IdentityServer/Controllers/Account/EditViewModel.cs
  class EditViewModel (line 8) | public class EditViewModel
    method EditViewModel (line 10) | public EditViewModel()
    method EditViewModel (line 14) | public EditViewModel(string Id, string Name, string LoginName, string ...

FILE: Blog.IdentityServer/Controllers/Account/ExternalController.cs
  class ExternalController (line 22) | [SecurityHeaders]
    method ExternalController (line 33) | public ExternalController(
    method Challenge (line 52) | [HttpGet]
    method Callback (line 82) | [HttpGet]
    method FindUserFromExternalProviderAsync (line 154) | private async Task<(ApplicationUser user, string provider, string prov...
    method AutoProvisionUserAsync (line 179) | private async Task<ApplicationUser> AutoProvisionUserAsync(string prov...
    method ProcessLoginCallback (line 240) | private void ProcessLoginCallback(AuthenticateResult externalResult, L...

FILE: Blog.IdentityServer/Controllers/Account/ExternalProvider.cs
  class ExternalProvider (line 7) | public class ExternalProvider

FILE: Blog.IdentityServer/Controllers/Account/ForgotPasswordViewModel.cs
  class ForgotPasswordViewModel (line 5) | public class ForgotPasswordViewModel

FILE: Blog.IdentityServer/Controllers/Account/LoggedOutViewModel.cs
  class LoggedOutViewModel (line 7) | public class LoggedOutViewModel

FILE: Blog.IdentityServer/Controllers/Account/LoginInputModel.cs
  class LoginInputModel (line 9) | public class LoginInputModel

FILE: Blog.IdentityServer/Controllers/Account/LoginViewModel.cs
  class LoginViewModel (line 11) | public class LoginViewModel : LoginInputModel

FILE: Blog.IdentityServer/Controllers/Account/LogoutInputModel.cs
  class LogoutInputModel (line 7) | public class LogoutInputModel

FILE: Blog.IdentityServer/Controllers/Account/LogoutViewModel.cs
  class LogoutViewModel (line 7) | public class LogoutViewModel : LogoutInputModel

FILE: Blog.IdentityServer/Controllers/Account/RedirectViewModel.cs
  class RedirectViewModel (line 8) | public class RedirectViewModel

FILE: Blog.IdentityServer/Controllers/Account/RegisterViewModel.cs
  class RegisterViewModel (line 6) | public class RegisterViewModel

FILE: Blog.IdentityServer/Controllers/Account/ResetPasswordViewModel.cs
  class ResetPasswordViewModel (line 5) | public class ResetPasswordViewModel

FILE: Blog.IdentityServer/Controllers/Account/RoleEditViewModel.cs
  class RoleEditViewModel (line 6) | public class RoleEditViewModel
    method RoleEditViewModel (line 8) | public RoleEditViewModel()
    method RoleEditViewModel (line 12) | public RoleEditViewModel(string Id, string Name)

FILE: Blog.IdentityServer/Controllers/Account/RoleRegisterViewModel.cs
  class RoleRegisterViewModel (line 6) | public class RoleRegisterViewModel

FILE: Blog.IdentityServer/Controllers/Account/UrlHelperExtensions.cs
  class UrlHelperExtensions (line 5) | public static class UrlHelperExtensions
    method EmailConfirmationLink (line 7) | public static string EmailConfirmationLink(this IUrlHelper urlHelper, ...
    method ResetPasswordCallbackLink (line 16) | public static string ResetPasswordCallbackLink(this IUrlHelper urlHelp...

FILE: Blog.IdentityServer/Controllers/ApiResource/ApiResourceDto.cs
  class ApiResourceDto (line 8) | public class ApiResourceDto

FILE: Blog.IdentityServer/Controllers/ApiResource/ApiResourcesManager.cs
  class ApiResourcesManager (line 14) | [Route("[controller]/[action]")]
    method ApiResourcesManager (line 20) | public ApiResourcesManager(ConfigurationDbContext configurationDbContext)
    method Index (line 29) | [HttpGet]
    method CreateOrEdit (line 44) | [HttpGet]
    method GetDataById (line 53) | [HttpGet]
    method SaveData (line 83) | [HttpPost]

FILE: Blog.IdentityServer/Controllers/Client/ClientDto.cs
  class ClientDto (line 3) | public class ClientDto

FILE: Blog.IdentityServer/Controllers/Client/ClientsManagerController.cs
  class ClientsManagerController (line 19) | [Route("[controller]/[action]")]
    method ClientsManagerController (line 25) | public ClientsManagerController(ConfigurationDbContext configurationDb...
    method Index (line 34) | [HttpGet]
    method CreateOrEdit (line 52) | [HttpGet]
    method GetDataById (line 61) | [HttpGet]
    method SaveData (line 100) | [HttpPost]

FILE: Blog.IdentityServer/Controllers/Consent/ConsentController.cs
  class ConsentController (line 23) | [SecurityHeaders]
    method ConsentController (line 31) | public ConsentController(
    method Index (line 46) | [HttpGet]
    method Index (line 61) | [HttpPost]
    method ProcessConsent (line 96) | private async Task<ProcessConsentResult> ProcessConsent(ConsentInputMo...
    method BuildViewModelAsync (line 164) | private async Task<ConsentViewModel> BuildViewModelAsync(string return...
    method CreateConsentViewModel (line 179) | private ConsentViewModel CreateConsentViewModel(
    method CreateScopeViewModel (line 218) | private ScopeViewModel CreateScopeViewModel(IdentityResource identity,...
    method CreateScopeViewModel (line 231) | public ScopeViewModel CreateScopeViewModel(ParsedScopeValue parsedScop...
    method GetOfflineAccessScope (line 250) | private ScopeViewModel GetOfflineAccessScope(bool check)

FILE: Blog.IdentityServer/Controllers/Consent/ConsentInputModel.cs
  class ConsentInputModel (line 9) | public class ConsentInputModel

FILE: Blog.IdentityServer/Controllers/Consent/ConsentOptions.cs
  class ConsentOptions (line 7) | public class ConsentOptions

FILE: Blog.IdentityServer/Controllers/Consent/ConsentViewModel.cs
  class ConsentViewModel (line 9) | public class ConsentViewModel : ConsentInputModel

FILE: Blog.IdentityServer/Controllers/Consent/ProcessConsentResult.cs
  class ProcessConsentResult (line 8) | public class ProcessConsentResult

FILE: Blog.IdentityServer/Controllers/Consent/ScopeViewModel.cs
  class ScopeViewModel (line 7) | public class ScopeViewModel

FILE: Blog.IdentityServer/Controllers/Device/DeviceAuthorizationInputModel.cs
  class DeviceAuthorizationInputModel (line 7) | public class DeviceAuthorizationInputModel : ConsentInputModel

FILE: Blog.IdentityServer/Controllers/Device/DeviceAuthorizationViewModel.cs
  class DeviceAuthorizationViewModel (line 7) | public class DeviceAuthorizationViewModel : ConsentViewModel

FILE: Blog.IdentityServer/Controllers/Device/DeviceController.cs
  class DeviceController (line 22) | [Authorize]
    method DeviceController (line 31) | public DeviceController(
    method Index (line 43) | [HttpGet]
    method UserCodeCapture (line 57) | [HttpPost]
    method Callback (line 67) | [HttpPost]
    method ProcessConsent (line 79) | private async Task<ProcessConsentResult> ProcessConsent(DeviceAuthoriz...
    method BuildViewModelAsync (line 146) | private async Task<DeviceAuthorizationViewModel> BuildViewModelAsync(s...
    method CreateConsentViewModel (line 157) | private DeviceAuthorizationViewModel CreateConsentViewModel(string use...
    method CreateScopeViewModel (line 194) | private ScopeViewModel CreateScopeViewModel(IdentityResource identity,...
    method CreateScopeViewModel (line 207) | public ScopeViewModel CreateScopeViewModel(ParsedScopeValue parsedScop...
    method GetOfflineAccessScope (line 220) | private ScopeViewModel GetOfflineAccessScope(bool check)

FILE: Blog.IdentityServer/Controllers/Diagnostics/DiagnosticsController.cs
  class DiagnosticsController (line 13) | [SecurityHeaders]
    method Index (line 17) | public async Task<IActionResult> Index()

FILE: Blog.IdentityServer/Controllers/Diagnostics/DiagnosticsViewModel.cs
  class DiagnosticsViewModel (line 13) | public class DiagnosticsViewModel
    method DiagnosticsViewModel (line 15) | public DiagnosticsViewModel(AuthenticateResult result)

FILE: Blog.IdentityServer/Controllers/Extensions.cs
  class Extensions (line 9) | public static class Extensions
    method IsPkceClientAsync (line 17) | public static async Task<bool> IsPkceClientAsync(this IClientStore sto...
    method IsNativeClient (line 32) | public static bool IsNativeClient(this AuthorizationRequest context)
    method LoadingPage (line 38) | public static IActionResult LoadingPage(this Controller controller, st...

FILE: Blog.IdentityServer/Controllers/Grants/GrantsController.cs
  class GrantsController (line 20) | [SecurityHeaders]
    method GrantsController (line 29) | public GrantsController(IIdentityServerInteractionService interaction,
    method Index (line 43) | [HttpGet]
    method Revoke (line 52) | [HttpPost]
    method BuildViewModelAsync (line 62) | private async Task<GrantsViewModel> BuildViewModelAsync()
    method Config (line 98) | [HttpGet]

FILE: Blog.IdentityServer/Controllers/Grants/GrantsViewModel.cs
  class GrantsViewModel (line 10) | public class GrantsViewModel
  class GrantViewModel (line 15) | public class GrantViewModel

FILE: Blog.IdentityServer/Controllers/Home/ErrorViewModel.cs
  class ErrorViewModel (line 9) | public class ErrorViewModel

FILE: Blog.IdentityServer/Controllers/Home/HomeController.cs
  class HomeController (line 15) | [SecurityHeaders]
    method HomeController (line 23) | public HomeController(IIdentityServerInteractionService interaction, I...
    method Index (line 30) | public IActionResult Index()
    method Error (line 47) | public async Task<IActionResult> Error(string errorId)

FILE: Blog.IdentityServer/Controllers/Home/Is4ApiController.cs
  class Is4ApiController (line 12) | [Route("[controller]/[action]")]
    method Is4ApiController (line 18) | public Is4ApiController(UserManager<ApplicationUser> userManager)
    method GetAchieveUsers (line 24) | [HttpGet]

FILE: Blog.IdentityServer/Controllers/SecurityHeadersAttribute.cs
  class SecurityHeadersAttribute (line 10) | public class SecurityHeadersAttribute : ActionFilterAttribute
    method OnResultExecuting (line 12) | public override void OnResultExecuting(ResultExecutingContext context)

FILE: Blog.IdentityServer/Controllers/TestUsers.cs
  class TestUsers (line 12) | public class TestUsers

FILE: Blog.IdentityServer/Data/ApplicationDbContext.cs
  class ApplicationDbContext (line 24) | public class ApplicationDbContext
    method ApplicationDbContext (line 29) | public ApplicationDbContext(DbContextOptions<ApplicationDbContext> opt...
    method OnModelCreating (line 34) | protected override void OnModelCreating(ModelBuilder builder)

FILE: Blog.IdentityServer/Data/MigrationsMySql/20200509165505_AppDbMigration.Designer.cs
  class AppDbMigration (line 11) | [DbContext(typeof(ApplicationDbContext))]
    method BuildTargetModel (line 15) | protected override void BuildTargetModel(ModelBuilder modelBuilder)

FILE: Blog.IdentityServer/Data/MigrationsMySql/20200509165505_AppDbMigration.cs
  class AppDbMigration (line 7) | public partial class AppDbMigration : Migration
    method Up (line 9) | protected override void Up(MigrationBuilder migrationBuilder)
    method Down (line 237) | protected override void Down(MigrationBuilder migrationBuilder)

FILE: Blog.IdentityServer/Data/MigrationsMySql/20210808045732_addQuestion.Designer.cs
  class addQuestion (line 11) | [DbContext(typeof(ApplicationDbContext))]
    method BuildTargetModel (line 15) | protected override void BuildTargetModel(ModelBuilder modelBuilder)

FILE: Blog.IdentityServer/Data/MigrationsMySql/20210808045732_addQuestion.cs
  class addQuestion (line 5) | public partial class addQuestion : Migration
    method Up (line 7) | protected override void Up(MigrationBuilder migrationBuilder)
    method Down (line 20) | protected override void Down(MigrationBuilder migrationBuilder)

FILE: Blog.IdentityServer/Data/MigrationsMySql/ApplicationDbContextModelSnapshot.cs
  class ApplicationDbContextModelSnapshot (line 10) | [DbContext(typeof(ApplicationDbContext))]
    method BuildModel (line 13) | protected override void BuildModel(ModelBuilder modelBuilder)

FILE: Blog.IdentityServer/Data/MigrationsMySql/IdentityServer/ConfigurationDb/20200509165153_InitialIdentityServerConfigurationDbMigrationMysql.Designer.cs
  class InitialIdentityServerConfigurationDbMigrationMysql (line 11) | [DbContext(typeof(ConfigurationDbContext))]
    method BuildTargetModel (line 15) | protected override void BuildTargetModel(ModelBuilder modelBuilder)

FILE: Blog.IdentityServer/Data/MigrationsMySql/IdentityServer/ConfigurationDb/20200509165153_InitialIdentityServerConfigurationDbMigrationMysql.cs
  class InitialIdentityServerConfigurationDbMigrationMysql (line 7) | public partial class InitialIdentityServerConfigurationDbMigrationMysql ...
    method Up (line 9) | protected override void Up(MigrationBuilder migrationBuilder)
    method Down (line 548) | protected override void Down(MigrationBuilder migrationBuilder)

FILE: Blog.IdentityServer/Data/MigrationsMySql/IdentityServer/ConfigurationDb/20200715033226_InitConfigurationDbV4.Designer.cs
  class InitConfigurationDbV4 (line 11) | [DbContext(typeof(ConfigurationDbContext))]
    method BuildTargetModel (line 15) | protected override void BuildTargetModel(ModelBuilder modelBuilder)

FILE: Blog.IdentityServer/Data/MigrationsMySql/IdentityServer/ConfigurationDb/20200715033226_InitConfigurationDbV4.cs
  class InitConfigurationDbV4 (line 7) | public partial class InitConfigurationDbV4 : Migration
    method Up (line 9) | protected override void Up(MigrationBuilder migrationBuilder)
    method Down (line 286) | protected override void Down(MigrationBuilder migrationBuilder)

FILE: Blog.IdentityServer/Data/MigrationsMySql/IdentityServer/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs
  class ConfigurationDbContextModelSnapshot (line 10) | [DbContext(typeof(ConfigurationDbContext))]
    method BuildModel (line 13) | protected override void BuildModel(ModelBuilder modelBuilder)

FILE: Blog.IdentityServer/Data/MigrationsMySql/IdentityServer/PersistedGrantDb/20200509165052_InitialIdentityServerPersistedGrantDbMigrationMysql.Designer.cs
  class InitialIdentityServerPersistedGrantDbMigrationMysql (line 11) | [DbContext(typeof(PersistedGrantDbContext))]
    method BuildTargetModel (line 15) | protected override void BuildTargetModel(ModelBuilder modelBuilder)

FILE: Blog.IdentityServer/Data/MigrationsMySql/IdentityServer/PersistedGrantDb/20200509165052_InitialIdentityServerPersistedGrantDbMigrationMysql.cs
  class InitialIdentityServerPersistedGrantDbMigrationMysql (line 6) | public partial class InitialIdentityServerPersistedGrantDbMigrationMysql...
    method Up (line 8) | protected override void Up(MigrationBuilder migrationBuilder)
    method Down (line 66) | protected override void Down(MigrationBuilder migrationBuilder)

FILE: Blog.IdentityServer/Data/MigrationsMySql/IdentityServer/PersistedGrantDb/20200715032957_InitPersistedGrantDbV4.Designer.cs
  class InitPersistedGrantDbV4 (line 11) | [DbContext(typeof(PersistedGrantDbContext))]
    method BuildTargetModel (line 15) | protected override void BuildTargetModel(ModelBuilder modelBuilder)

FILE: Blog.IdentityServer/Data/MigrationsMySql/IdentityServer/PersistedGrantDb/20200715032957_InitPersistedGrantDbV4.cs
  class InitPersistedGrantDbV4 (line 6) | public partial class InitPersistedGrantDbV4 : Migration
    method Up (line 8) | protected override void Up(MigrationBuilder migrationBuilder)
    method Down (line 45) | protected override void Down(MigrationBuilder migrationBuilder)

FILE: Blog.IdentityServer/Data/MigrationsMySql/IdentityServer/PersistedGrantDb/PersistedGrantDbContextModelSnapshot.cs
  class PersistedGrantDbContextModelSnapshot (line 10) | [DbContext(typeof(PersistedGrantDbContext))]
    method BuildModel (line 13) | protected override void BuildModel(ModelBuilder modelBuilder)

FILE: Blog.IdentityServer/Extensions/GrantTypeCustom.cs
  class GrantTypeCustom (line 11) | public class GrantTypeCustom

FILE: Blog.IdentityServer/Extensions/IpLimitMildd.cs
  class IpLimitMildd (line 7) | public static class IpLimitMildd
    method UseIpLimitMildd (line 9) | public static void UseIpLimitMildd(this IApplicationBuilder app)

FILE: Blog.IdentityServer/Extensions/IpPolicyRateLimitSetup.cs
  class IpPolicyRateLimitSetup (line 9) | public static class IpPolicyRateLimitSetup
    method AddIpPolicyRateLimitSetup (line 11) | public static void AddIpPolicyRateLimitSetup(this IServiceCollection s...

FILE: Blog.IdentityServer/Extensions/ResourceOwnerPasswordValidator.cs
  class ResourceOwnerPasswordValidator (line 11) | public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordVali...
    method ValidateAsync (line 13) | public async Task ValidateAsync(ResourceOwnerPasswordValidationContext...
    method ValidateUserAsync (line 48) | private async Task<List<Claim>> ValidateUserAsync(string loginName, st...

FILE: Blog.IdentityServer/Extensions/WeiXinOpenGrantValidator.cs
  class WeiXinOpenGrantValidator (line 11) | public class WeiXinOpenGrantValidator : IExtensionGrantValidator
    method ValidateAsync (line 15) | public async Task ValidateAsync(ExtensionGrantValidationContext context)
    method ValidateUserAsync (line 51) | private async Task<List<Claim>> ValidateUserAsync(string openId, strin...

FILE: Blog.IdentityServer/Helper/Appsettings.cs
  class Appsettings (line 11) | public class Appsettings
    method Appsettings (line 23) | static Appsettings()
    method app (line 48) | public static string app(params string[] sections)

FILE: Blog.IdentityServer/Helper/FileHelper.cs
  class FileHelper (line 7) | public class FileHelper : IDisposable
    method FileHelper (line 13) | public FileHelper()
    method Dispose (line 24) | protected virtual void Dispose(bool isDisposing)
    method Dispose (line 33) | public void Dispose()
    method GetPostfixStr (line 55) | public static string GetPostfixStr(string filename)
    method WriteFile (line 79) | public static void WriteFile(string Path, string Strings)
    method WriteFile (line 98) | public static void WriteFile(string Path, string Strings, Encoding enc...
    method ReadFile (line 126) | public static string ReadFile(string Path)
    method ReadFile (line 148) | public static string ReadFile(string Path, Encoding encode)
    method FileAdd (line 180) | public static void FileAdd(string Path, string strings)
    method FileCoppy (line 204) | public static void FileCoppy(string orignFile, string NewFile)
    method FileDel (line 224) | public static void FileDel(string Path)
    method FileMove (line 245) | public static void FileMove(string orignFile, string NewFile)
    method FolderCreate (line 266) | public static void FolderCreate(string orignFolder, string NewFloder)
    method DeleteFolder (line 287) | public static void DeleteFolder(string dir)
    method CopyDir (line 319) | public static void CopyDir(string srcPath, string aimPath)

FILE: Blog.IdentityServer/Helper/GetNetData.cs
  class GetNetData (line 7) | public class GetNetData
    method Get (line 9) | public static string Get(string serviceAddress)
    method Post (line 25) | public static string Post(string serviceAddress)

FILE: Blog.IdentityServer/Helper/HtmlHelper.cs
  class HtmlHelper (line 3) | public static class HtmlHelper
    method ReplaceHtmlTag (line 12) | public static string ReplaceHtmlTag(string html, int length = 0)

FILE: Blog.IdentityServer/Helper/JsonHelper.cs
  class JsonHelper (line 6) | public class JsonHelper
    method GetJSON (line 14) | public static string GetJSON<T>(object obj)
    method JSON (line 39) | public string JSON<T>(List<T> vals)
    method ParseFormByJson (line 68) | public static T ParseFormByJson<T>(string jsonStr)
    method JSON1 (line 80) | public string JSON1<SendData>(List<SendData> vals)

FILE: Blog.IdentityServer/Helper/MD5Hepler.cs
  class MD5Helper (line 7) | public class MD5Helper
    method MD5Encrypt16 (line 14) | public static string MD5Encrypt16(string password)
    method MD5Encrypt32 (line 27) | public static string MD5Encrypt32(string password = "")
    method MD5Encrypt64 (line 57) | public static string MD5Encrypt64(string password)

FILE: Blog.IdentityServer/Helper/RecursionHelper.cs
  class RecursionHelper (line 9) | public static class RecursionHelper
    method LoopToAppendChildren (line 11) | public static void LoopToAppendChildren(List<PermissionTree> all, Perm...
    method LoopNaviBarAppendChildren (line 58) | public static void LoopNaviBarAppendChildren(List<NavigationBar> all, ...
    method LoopToAppendChildrenT (line 82) | public static void LoopToAppendChildrenT<T>(List<T> all, T curItem, st...
  class PermissionTree (line 94) | public class PermissionTree
  class NavigationBar (line 105) | public class NavigationBar
  class NavigationBarMeta (line 117) | public class NavigationBarMeta

FILE: Blog.IdentityServer/Helper/SerializeHelper.cs
  class SerializeHelper (line 6) | public class SerializeHelper
    method Serialize (line 13) | public static byte[] Serialize(object item)
    method Deserialize (line 25) | public static TEntity Deserialize<TEntity>(byte[] value)

FILE: Blog.IdentityServer/Helper/UnicodeHelper.cs
  class UnicodeHelper (line 7) | public static class UnicodeHelper
    method StringToUnicode (line 14) | public static string StringToUnicode(string value)
    method UnicodeToString (line 31) | public static string UnicodeToString(string unicode)

FILE: Blog.IdentityServer/Helper/UtilConvert.cs
  class UtilConvert (line 7) | public static class UtilConvert
    method ObjToInt (line 14) | public static int ObjToInt(this object thisValue)
    method ObjToInt (line 30) | public static int ObjToInt(this object thisValue, int errorValue)
    method ObjToMoney (line 44) | public static double ObjToMoney(this object thisValue)
    method ObjToMoney (line 59) | public static double ObjToMoney(this object thisValue, double errorValue)
    method ObjToString (line 73) | public static string ObjToString(this object thisValue)
    method ObjToString (line 84) | public static string ObjToString(this object thisValue, string errorVa...
    method ObjToDecimal (line 94) | public static Decimal ObjToDecimal(this object thisValue)
    method ObjToDecimal (line 109) | public static Decimal ObjToDecimal(this object thisValue, decimal erro...
    method ObjToDate (line 123) | public static DateTime ObjToDate(this object thisValue)
    method ObjToDate (line 138) | public static DateTime ObjToDate(this object thisValue, DateTime error...
    method ObjToBool (line 152) | public static bool ObjToBool(this object thisValue)

FILE: Blog.IdentityServer/InMemoryConfig.cs
  class InMemoryConfig (line 10) | public static class InMemoryConfig
    method GetApiResources (line 13) | public static IEnumerable<ApiResource> GetApiResources()
    method GetClients (line 21) | public static IEnumerable<Client> GetClients()
    method Users (line 35) | public static IEnumerable<TestUser> Users()

FILE: Blog.IdentityServer/Models/ApplicationRole.cs
  class ApplicationRole (line 8) | public class ApplicationRole : IdentityRole<int>

FILE: Blog.IdentityServer/Models/ApplicationUser.cs
  class ApplicationUser (line 8) | public class ApplicationUser : IdentityUser<int>

FILE: Blog.IdentityServer/Models/ApplicationUserRole.cs
  class ApplicationUserRole (line 5) | public class ApplicationUserRole : IdentityUserRole<int>

FILE: Blog.IdentityServer/Models/Bak/Role.cs
  class Role (line 8) | public class Role : RootEntity
    method Role (line 10) | public Role()
    method Role (line 17) | public Role(string name)

FILE: Blog.IdentityServer/Models/Bak/RootEntity.cs
  class RootEntity (line 3) | public class RootEntity

FILE: Blog.IdentityServer/Models/Bak/UserRole.cs
  class UserRole (line 8) | public class UserRole : RootEntity
    method UserRole (line 10) | public UserRole() { }
    method UserRole (line 12) | public UserRole(int uid, int rid)

FILE: Blog.IdentityServer/Models/Bak/sysUserInfo.cs
  class sysUserInfo (line 8) | public class sysUserInfo
    method sysUserInfo (line 10) | public sysUserInfo() { }
    method sysUserInfo (line 12) | public sysUserInfo(string loginName, string loginPWD)

FILE: Blog.IdentityServer/Models/Dtos/MessageModel.cs
  class MessageModel (line 11) | public class MessageModel<T>

FILE: Blog.IdentityServer/Models/ViewModel/AccessApiDateView.cs
  class AccessApiDateView (line 8) | public class AccessApiDateView
  class ApiDate (line 14) | public class ApiDate

FILE: Blog.IdentityServer/Program.cs
  class Program (line 14) | public class Program
    method Main (line 16) | public static void Main(string[] args)
    method CreateHostBuilder (line 46) | public static IHostBuilder CreateHostBuilder(string[] args) =>

FILE: Blog.IdentityServer/SameSiteHandlingExtensions.cs
  class SameSiteHandlingExtensions (line 8) | public static class SameSiteHandlingExtensions
    method AddSameSiteCookiePolicy (line 10) | public static IServiceCollection AddSameSiteCookiePolicy(this IService...
    method CheckSameSite (line 24) | private static void CheckSameSite(HttpContext httpContext, CookieOptio...
    method DisallowsSameSiteNone (line 37) | private static bool DisallowsSameSiteNone(string userAgent)

FILE: Blog.IdentityServer/SeedData.cs
  class SeedData (line 19) | public class SeedData
    method EnsureSeedData (line 23) | public static void EnsureSeedData(IServiceProvider serviceProvider)
    method EnsureSeedData (line 207) | private static void EnsureSeedData(ConfigurationDbContext context)

FILE: Blog.IdentityServer/Startup.cs
  class Startup (line 22) | public class Startup
    method Startup (line 27) | public Startup(IConfiguration configuration, IWebHostEnvironment envir...
    method ConfigureServices (line 33) | public void ConfigureServices(IServiceCollection services)
    method Configure (line 213) | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

FILE: Blog.IdentityServer/wwwroot/js/showTip.js
  function ShowTip (line 2) | function ShowTip(tip, type) {
  function ShowMsg (line 11) | function ShowMsg(msg) {
  function ShowSuccess (line 15) | function ShowSuccess(msg) {
  function ShowFailure (line 19) | function ShowFailure(msg) {
  function ShowWarn (line 23) | function ShowWarn(msg, $focus, clear) {

FILE: Blog.IdentityServer/wwwroot/lib/bootstrap/js/bootstrap.js
  function transitionEnd (line 34) | function transitionEnd() {
  function removeElement (line 126) | function removeElement() {
  function Plugin (line 142) | function Plugin(option) {
  function Plugin (line 251) | function Plugin(option) {
  function Plugin (line 470) | function Plugin(option) {
  function getTargetFromTrigger (line 689) | function getTargetFromTrigger($trigger) {
  function Plugin (line 701) | function Plugin(option) {
  function getParent (line 768) | function getParent($this) {
  function clearMenus (line 781) | function clearMenus(e) {
  function Plugin (line 874) | function Plugin(option) {
  function Plugin (line 1200) | function Plugin(option, _relatedTarget) {
  function complete (line 1566) | function complete() {
  function Plugin (line 1736) | function Plugin(option) {
  function Plugin (line 1845) | function Plugin(option) {
  function ScrollSpy (line 1888) | function ScrollSpy(element, options) {
  function Plugin (line 2008) | function Plugin(option) {
  function next (line 2117) | function next() {
  function Plugin (line 2163) | function Plugin(option) {
  function Plugin (line 2320) | function Plugin(option) {

FILE: Blog.IdentityServer/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js
  function setValidationValues (line 14) | function setValidationValues(options, ruleName, value) {
  function splitAndTrim (line 21) | function splitAndTrim(value) {
  function escapeAttributeValue (line 25) | function escapeAttributeValue(value) {
  function getModelPrefix (line 30) | function getModelPrefix(fieldName) {
  function appendModelPrefix (line 34) | function appendModelPrefix(value, prefix) {
  function onError (line 41) | function onError(error, inputElement) {  // 'this' is the form element
  function onErrors (line 58) | function onErrors(event, validator) {  // 'this' is the form element
  function onSuccess (line 72) | function onSuccess(error) {  // 'this' is the form element
  function onReset (line 88) | function onReset(event) {  // 'this' is the form element
  function validationInfo (line 113) | function validationInfo(form) {

FILE: Blog.IdentityServer/wwwroot/lib/jquery-validation/dist/additional-methods.js
  function stripHtml (line 19) | function stripHtml(value) {

FILE: Blog.IdentityServer/wwwroot/lib/jquery-validation/dist/jquery.validate.js
  function handle (line 65) | function handle() {
  function delegate (line 375) | function delegate( event ) {

FILE: Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/additional.js
  function stripHtml (line 3) | function stripHtml(value) {

FILE: Blog.IdentityServer/wwwroot/lib/jquery-validation/src/core.js
  function handle (line 49) | function handle() {
  function delegate (line 359) | function delegate( event ) {
Condensed preview — 277 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,193K chars).
[
  {
    "path": ".dockerignore",
    "chars": 316,
    "preview": "**/.classpath\n**/.dockerignore\n**/.env\n**/.git\n**/.gitignore\n**/.project\n**/.settings\n**/.toolstarget\n**/.vs\n**/.vscode\n"
  },
  {
    "path": ".gitattributes",
    "chars": 2518,
    "preview": "###############################################################################\n# Set default behavior to automatically "
  },
  {
    "path": ".gitignore",
    "chars": 4314,
    "preview": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User"
  },
  {
    "path": "Blog.IdentityServer/Authorization/ClaimRequirement.cs",
    "chars": 420,
    "preview": "using Microsoft.AspNetCore.Authorization;\n\nnamespace Blog.IdentityServer.Authorization\n{\n    public class ClaimRequirem"
  },
  {
    "path": "Blog.IdentityServer/Authorization/ClaimsRequirementHandler.cs",
    "chars": 725,
    "preview": "using System.Linq;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Authorization;\n\nnamespace Blog.IdentityServ"
  },
  {
    "path": "Blog.IdentityServer/Blog.IdentityServer.csproj",
    "chars": 3438,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp3.1</TargetFramework>\n    <User"
  },
  {
    "path": "Blog.IdentityServer/Config.cs",
    "chars": 9946,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. "
  },
  {
    "path": "Blog.IdentityServer/Controllers/Account/AccountController.cs",
    "chars": 50059,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. "
  },
  {
    "path": "Blog.IdentityServer/Controllers/Account/AccountOptions.cs",
    "chars": 1037,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. "
  },
  {
    "path": "Blog.IdentityServer/Controllers/Account/EditViewModel.cs",
    "chars": 1456,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.ComponentModel.DataAnnotations;\nusing System.Security.Clai"
  },
  {
    "path": "Blog.IdentityServer/Controllers/Account/ExternalController.cs",
    "chars": 11277,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Security.Claims;\nusing System.Threading."
  },
  {
    "path": "Blog.IdentityServer/Controllers/Account/ExternalProvider.cs",
    "chars": 373,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. "
  },
  {
    "path": "Blog.IdentityServer/Controllers/Account/ForgotPasswordViewModel.cs",
    "chars": 415,
    "preview": "using System.ComponentModel.DataAnnotations;\n\nnamespace IdentityServer4.Quickstart.UI\n{\n    public class ForgotPassword"
  },
  {
    "path": "Blog.IdentityServer/Controllers/Account/LoggedOutViewModel.cs",
    "chars": 696,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. S"
  },
  {
    "path": "Blog.IdentityServer/Controllers/Account/LoginInputModel.cs",
    "chars": 534,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. S"
  },
  {
    "path": "Blog.IdentityServer/Controllers/Account/LoginViewModel.cs",
    "chars": 975,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. S"
  },
  {
    "path": "Blog.IdentityServer/Controllers/Account/LogoutInputModel.cs",
    "chars": 314,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. "
  },
  {
    "path": "Blog.IdentityServer/Controllers/Account/LogoutViewModel.cs",
    "chars": 345,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. S"
  },
  {
    "path": "Blog.IdentityServer/Controllers/Account/RedirectViewModel.cs",
    "chars": 317,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. S"
  },
  {
    "path": "Blog.IdentityServer/Controllers/Account/RegisterViewModel.cs",
    "chars": 1317,
    "preview": "using System;\nusing System.ComponentModel.DataAnnotations;\n\nnamespace IdentityServer4.Quickstart.UI\n{\n    public class "
  },
  {
    "path": "Blog.IdentityServer/Controllers/Account/ResetPasswordViewModel.cs",
    "chars": 845,
    "preview": "using System.ComponentModel.DataAnnotations;\n\nnamespace IdentityServer4.Quickstart.UI\n{\n    public class ResetPasswordV"
  },
  {
    "path": "Blog.IdentityServer/Controllers/Account/RoleEditViewModel.cs",
    "chars": 502,
    "preview": "using System;\nusing System.ComponentModel.DataAnnotations;\n\nnamespace IdentityServer4.Quickstart.UI\n{\n    public class "
  },
  {
    "path": "Blog.IdentityServer/Controllers/Account/RoleRegisterViewModel.cs",
    "chars": 263,
    "preview": "using System;\nusing System.ComponentModel.DataAnnotations;\n\nnamespace IdentityServer4.Quickstart.UI\n{\n    public class "
  },
  {
    "path": "Blog.IdentityServer/Controllers/Account/UrlHelperExtensions.cs",
    "chars": 899,
    "preview": "using Microsoft.AspNetCore.Mvc;\n\nnamespace IdentityServer4.Quickstart.UI\n{\n    public static class UrlHelperExtensions\n "
  },
  {
    "path": "Blog.IdentityServer/Controllers/ApiResource/ApiResourceDto.cs",
    "chars": 464,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\n\nnamespace Blog.Identi"
  },
  {
    "path": "Blog.IdentityServer/Controllers/ApiResource/ApiResourcesManager.cs",
    "chars": 5758,
    "preview": "using System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Blog.IdentityServer.Models;\nus"
  },
  {
    "path": "Blog.IdentityServer/Controllers/Client/ClientDto.cs",
    "chars": 649,
    "preview": "namespace Blog.IdentityServer.Controllers.Client\n{\n    public class ClientDto\n    {\n        public int id { get; set; }"
  },
  {
    "path": "Blog.IdentityServer/Controllers/Client/ClientsManagerController.cs",
    "chars": 9822,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Blog.Core.Common"
  },
  {
    "path": "Blog.IdentityServer/Controllers/Consent/ConsentController.cs",
    "chars": 9960,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. S"
  },
  {
    "path": "Blog.IdentityServer/Controllers/Consent/ConsentInputModel.cs",
    "chars": 556,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. "
  },
  {
    "path": "Blog.IdentityServer/Controllers/Consent/ConsentOptions.cs",
    "chars": 722,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. "
  },
  {
    "path": "Blog.IdentityServer/Controllers/Consent/ConsentViewModel.cs",
    "chars": 662,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. "
  },
  {
    "path": "Blog.IdentityServer/Controllers/Consent/ProcessConsentResult.cs",
    "chars": 676,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. S"
  },
  {
    "path": "Blog.IdentityServer/Controllers/Consent/ScopeViewModel.cs",
    "chars": 534,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. "
  },
  {
    "path": "Blog.IdentityServer/Controllers/Device/DeviceAuthorizationInputModel.cs",
    "chars": 352,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. S"
  },
  {
    "path": "Blog.IdentityServer/Controllers/Device/DeviceAuthorizationViewModel.cs",
    "chars": 400,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. S"
  },
  {
    "path": "Blog.IdentityServer/Controllers/Device/DeviceController.cs",
    "chars": 9338,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. S"
  },
  {
    "path": "Blog.IdentityServer/Controllers/Diagnostics/DiagnosticsController.cs",
    "chars": 957,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. S"
  },
  {
    "path": "Blog.IdentityServer/Controllers/Diagnostics/DiagnosticsViewModel.cs",
    "chars": 1030,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. S"
  },
  {
    "path": "Blog.IdentityServer/Controllers/Extensions.cs",
    "chars": 1629,
    "preview": "using System;\nusing System.Threading.Tasks;\nusing IdentityServer4.Models;\nusing IdentityServer4.Stores;\nusing Microsoft."
  },
  {
    "path": "Blog.IdentityServer/Controllers/Grants/GrantsController.cs",
    "chars": 3465,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. S"
  },
  {
    "path": "Blog.IdentityServer/Controllers/Grants/GrantsViewModel.cs",
    "chars": 885,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. "
  },
  {
    "path": "Blog.IdentityServer/Controllers/Home/ErrorViewModel.cs",
    "chars": 345,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. "
  },
  {
    "path": "Blog.IdentityServer/Controllers/Home/HomeController.cs",
    "chars": 2049,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. S"
  },
  {
    "path": "Blog.IdentityServer/Controllers/Home/Is4ApiController.cs",
    "chars": 2024,
    "preview": "using Blog.IdentityServer.Models;\nusing Blog.IdentityServer.Models.ViewModel;\nusing Microsoft.AspNetCore.Identity;\nusin"
  },
  {
    "path": "Blog.IdentityServer/Controllers/SecurityHeadersAttribute.cs",
    "chars": 2743,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. "
  },
  {
    "path": "Blog.IdentityServer/Controllers/TestUsers.cs",
    "chars": 2171,
    "preview": "// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.\n// Licensed under the Apache License, Version 2.0. "
  },
  {
    "path": "Blog.IdentityServer/Data/ApplicationDbContext.cs",
    "chars": 2025,
    "preview": "using Microsoft.AspNetCore.Identity.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore;\nusing Blog.IdentityServer"
  },
  {
    "path": "Blog.IdentityServer/Data/MigrationsMySql/20200509165505_AppDbMigration.Designer.cs",
    "chars": 12535,
    "preview": "// <auto-generated />\nusing System;\nusing Blog.IdentityServer.Data;\nusing Microsoft.EntityFrameworkCore;\nusing Microsof"
  },
  {
    "path": "Blog.IdentityServer/Data/MigrationsMySql/20200509165505_AppDbMigration.cs",
    "chars": 11818,
    "preview": "using System;\nusing Microsoft.EntityFrameworkCore.Metadata;\nusing Microsoft.EntityFrameworkCore.Migrations;\n\nnamespace "
  },
  {
    "path": "Blog.IdentityServer/Data/MigrationsMySql/20210808045732_addQuestion.Designer.cs",
    "chars": 12792,
    "preview": "// <auto-generated />\nusing System;\nusing Blog.IdentityServer.Data;\nusing Microsoft.EntityFrameworkCore;\nusing Microsof"
  },
  {
    "path": "Blog.IdentityServer/Data/MigrationsMySql/20210808045732_addQuestion.cs",
    "chars": 907,
    "preview": "using Microsoft.EntityFrameworkCore.Migrations;\n\nnamespace Blog.IdentityServer.Data.MigrationsMySql\n{\n    public partia"
  },
  {
    "path": "Blog.IdentityServer/Data/MigrationsMySql/ApplicationDbContextModelSnapshot.cs",
    "chars": 12730,
    "preview": "// <auto-generated />\nusing System;\nusing Blog.IdentityServer.Data;\nusing Microsoft.EntityFrameworkCore;\nusing Microsof"
  },
  {
    "path": "Blog.IdentityServer/Data/MigrationsMySql/IdentityServer/ConfigurationDb/20200509165153_InitialIdentityServerConfigurationDbMigrationMysql.Designer.cs",
    "chars": 31226,
    "preview": "// <auto-generated />\nusing System;\nusing IdentityServer4.EntityFramework.DbContexts;\nusing Microsoft.EntityFrameworkCo"
  },
  {
    "path": "Blog.IdentityServer/Data/MigrationsMySql/IdentityServer/ConfigurationDb/20200509165153_InitialIdentityServerConfigurationDbMigrationMysql.cs",
    "chars": 28589,
    "preview": "using System;\nusing Microsoft.EntityFrameworkCore.Metadata;\nusing Microsoft.EntityFrameworkCore.Migrations;\n\nnamespace "
  },
  {
    "path": "Blog.IdentityServer/Data/MigrationsMySql/IdentityServer/ConfigurationDb/20200715033226_InitConfigurationDbV4.Designer.cs",
    "chars": 33889,
    "preview": "// <auto-generated />\nusing System;\nusing IdentityServer4.EntityFramework.DbContexts;\nusing Microsoft.EntityFrameworkCo"
  },
  {
    "path": "Blog.IdentityServer/Data/MigrationsMySql/IdentityServer/ConfigurationDb/20200715033226_InitConfigurationDbV4.cs",
    "chars": 20969,
    "preview": "using System;\nusing Microsoft.EntityFrameworkCore.Metadata;\nusing Microsoft.EntityFrameworkCore.Migrations;\n\nnamespace "
  },
  {
    "path": "Blog.IdentityServer/Data/MigrationsMySql/IdentityServer/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs",
    "chars": 33809,
    "preview": "// <auto-generated />\nusing System;\nusing IdentityServer4.EntityFramework.DbContexts;\nusing Microsoft.EntityFrameworkCo"
  },
  {
    "path": "Blog.IdentityServer/Data/MigrationsMySql/IdentityServer/PersistedGrantDb/20200509165052_InitialIdentityServerPersistedGrantDbMigrationMysql.Designer.cs",
    "chars": 4023,
    "preview": "// <auto-generated />\nusing System;\nusing IdentityServer4.EntityFramework.DbContexts;\nusing Microsoft.EntityFrameworkCo"
  },
  {
    "path": "Blog.IdentityServer/Data/MigrationsMySql/IdentityServer/PersistedGrantDb/20200509165052_InitialIdentityServerPersistedGrantDbMigrationMysql.cs",
    "chars": 3124,
    "preview": "using System;\nusing Microsoft.EntityFrameworkCore.Migrations;\n\nnamespace Blog.IdentityServer.Data.MigrationsMySql.Ident"
  },
  {
    "path": "Blog.IdentityServer/Data/MigrationsMySql/IdentityServer/PersistedGrantDb/20200715032957_InitPersistedGrantDbV4.Designer.cs",
    "chars": 4846,
    "preview": "// <auto-generated />\nusing System;\nusing IdentityServer4.EntityFramework.DbContexts;\nusing Microsoft.EntityFrameworkCo"
  },
  {
    "path": "Blog.IdentityServer/Data/MigrationsMySql/IdentityServer/PersistedGrantDb/20200715032957_InitPersistedGrantDbV4.cs",
    "chars": 2304,
    "preview": "using System;\nusing Microsoft.EntityFrameworkCore.Migrations;\n\nnamespace Blog.IdentityServer.Data.MigrationsMySql.Ident"
  },
  {
    "path": "Blog.IdentityServer/Data/MigrationsMySql/IdentityServer/PersistedGrantDb/PersistedGrantDbContextModelSnapshot.cs",
    "chars": 4765,
    "preview": "// <auto-generated />\nusing System;\nusing IdentityServer4.EntityFramework.DbContexts;\nusing Microsoft.EntityFrameworkCo"
  },
  {
    "path": "Blog.IdentityServer/Dockerfile",
    "chars": 159,
    "preview": "FROM swr.cn-south-1.myhuaweicloud.com/mcr/aspnet:3.1-alpine\nWORKDIR /app\nCOPY . . \nEXPOSE 5004 \nENTRYPOINT [\"dotnet\", \"B"
  },
  {
    "path": "Blog.IdentityServer/Extensions/GrantTypeCustom.cs",
    "chars": 382,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\n\nnamespace Blog.Identi"
  },
  {
    "path": "Blog.IdentityServer/Extensions/IpLimitMildd.cs",
    "chars": 510,
    "preview": "using AspNetCoreRateLimit;\nusing Microsoft.AspNetCore.Builder;\nusing System;\n\nnamespace Blog.IdentityServer.Extensions\n"
  },
  {
    "path": "Blog.IdentityServer/Extensions/IpPolicyRateLimitSetup.cs",
    "chars": 1515,
    "preview": "using AspNetCoreRateLimit;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.E"
  },
  {
    "path": "Blog.IdentityServer/Extensions/ResourceOwnerPasswordValidator.cs",
    "chars": 1884,
    "preview": "using Blog.IdentityServer.Models;\nusing IdentityServer4.Validation;\nusing System;\nusing System.Collections.Generic;\nusi"
  },
  {
    "path": "Blog.IdentityServer/Extensions/WeiXinOpenGrantValidator.cs",
    "chars": 2023,
    "preview": "using Blog.IdentityServer.Models;\nusing IdentityServer4.Validation;\nusing System;\nusing System.Collections.Generic;\nusi"
  },
  {
    "path": "Blog.IdentityServer/Helper/Appsettings.cs",
    "chars": 2053,
    "preview": "using Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.Configuration.Json;\nusing System;\nusing System.IO;"
  },
  {
    "path": "Blog.IdentityServer/Helper/FileHelper.cs",
    "chars": 11539,
    "preview": "using System;\nusing System.IO;\nusing System.Text;\n\nnamespace Blog.Core.Common.Helper\n{\n    public class FileHelper : ID"
  },
  {
    "path": "Blog.IdentityServer/Helper/GetNetData.cs",
    "chars": 1971,
    "preview": "using System.IO;\nusing System.Net;\nusing System.Text;\n\nnamespace Blog.Core.Common.Helper\n{\n    public class GetNetData\n"
  },
  {
    "path": "Blog.IdentityServer/Helper/HtmlHelper.cs",
    "chars": 739,
    "preview": "namespace Blog.Core.Common.Helper\n{\n    public static class HtmlHelper\n    {\n        #region 去除富文本中的HTML标签\n        /// "
  },
  {
    "path": "Blog.IdentityServer/Helper/JsonHelper.cs",
    "chars": 3603,
    "preview": "using System;\nusing System.Collections.Generic;\n\nnamespace Blog.Core.Common.Helper\n{\n    public class JsonHelper\n    {\n"
  },
  {
    "path": "Blog.IdentityServer/Helper/MD5Hepler.cs",
    "chars": 2141,
    "preview": "using System;\nusing System.Security.Cryptography;\nusing System.Text;\n\nnamespace Blog.Core.Common.Helper\n{\n    public cl"
  },
  {
    "path": "Blog.IdentityServer/Helper/RecursionHelper.cs",
    "chars": 3690,
    "preview": "using System.Collections.Generic;\nusing System.Linq;\n\nnamespace Blog.Core.Common.Helper\n{\n    /// <summary>\n    /// 泛型递"
  },
  {
    "path": "Blog.IdentityServer/Helper/SerializeHelper.cs",
    "chars": 955,
    "preview": "using Newtonsoft.Json;\nusing System.Text;\n\nnamespace Blog.Core.Common.Helper\n{\n    public class SerializeHelper\n    {\n "
  },
  {
    "path": "Blog.IdentityServer/Helper/UnicodeHelper.cs",
    "chars": 1338,
    "preview": "using System;\nusing System.Text;\nusing System.Text.RegularExpressions;\n\nnamespace Blog.Core.Common.Helper\n{\n    public "
  },
  {
    "path": "Blog.IdentityServer/Helper/UtilConvert.cs",
    "chars": 5243,
    "preview": "using System;\nnamespace Blog.IdentityServer\n{\n    /// <summary>\n    /// \n    /// </summary>\n    public static class Uti"
  },
  {
    "path": "Blog.IdentityServer/InMemoryConfig.cs",
    "chars": 1613,
    "preview": "using IdentityServer4.Models;\nusing IdentityServer4.Test;\nusing System;\nusing System.Collections.Generic;\nusing System."
  },
  {
    "path": "Blog.IdentityServer/LICENSE",
    "chars": 1067,
    "preview": "MIT License\n\nCopyright (c) 2019 ansonzhang\n\nPermission is hereby granted, free of charge, to any person obtaining a copy"
  },
  {
    "path": "Blog.IdentityServer/Models/ApplicationRole.cs",
    "chars": 1338,
    "preview": "using Microsoft.AspNetCore.Identity;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Blog.IdentityServer.Mod"
  },
  {
    "path": "Blog.IdentityServer/Models/ApplicationUser.cs",
    "chars": 786,
    "preview": "using Microsoft.AspNetCore.Identity;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Blog.IdentityServer.Mod"
  },
  {
    "path": "Blog.IdentityServer/Models/ApplicationUserRole.cs",
    "chars": 268,
    "preview": "using Microsoft.AspNetCore.Identity;\n\nnamespace Blog.IdentityServer.Models\n{\n    public class ApplicationUserRole : Ide"
  },
  {
    "path": "Blog.IdentityServer/Models/Bak/Role.cs",
    "chars": 1793,
    "preview": "using System;\n\nnamespace Blog.IdentityServer.Models\n{\n    /// <summary>\n    /// 角色表\n    /// </summary>\n    public class"
  },
  {
    "path": "Blog.IdentityServer/Models/Bak/RootEntity.cs",
    "chars": 185,
    "preview": "namespace Blog.IdentityServer.Models\n{\n    public class RootEntity\n    {\n        /// <summary>\n        /// ID\n        /"
  },
  {
    "path": "Blog.IdentityServer/Models/Bak/UserRole.cs",
    "chars": 1422,
    "preview": "using System;\n\nnamespace Blog.IdentityServer.Models\n{\n    /// <summary>\n    /// 用户跟角色关联表\n    /// </summary>\n    public "
  },
  {
    "path": "Blog.IdentityServer/Models/Bak/sysUserInfo.cs",
    "chars": 2100,
    "preview": "using System;\n\nnamespace Blog.IdentityServer.Models\n{\n    /// <summary>\n    /// 用户信息表\n    /// </summary>\n    public cla"
  },
  {
    "path": "Blog.IdentityServer/Models/Dtos/MessageModel.cs",
    "chars": 679,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\n\nnamespace Blog.Identi"
  },
  {
    "path": "Blog.IdentityServer/Models/ViewModel/AccessApiDateView.cs",
    "chars": 447,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\n\nnamespace Blog.Identi"
  },
  {
    "path": "Blog.IdentityServer/Program.cs",
    "chars": 2329,
    "preview": "using System;\nusing System.Linq;\nusing Blog.IdentityServer;\nusing Microsoft.AspNetCore;\nusing Microsoft.AspNetCore.Host"
  },
  {
    "path": "Blog.IdentityServer/Properties/PublishProfiles/FolderProfile.pubxml",
    "chars": 845,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n此文件由 Web 项目的发布/打包过程使用。可以通过编辑此 MSBuild 文件\n自定义此过程的行为。为了解与此相关的更多内容,请访问 https://"
  },
  {
    "path": "Blog.IdentityServer/Properties/launchSettings.json",
    "chars": 426,
    "preview": "{\n  \"profiles\": {\n    \"Blog.IdentityServer\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"launc"
  },
  {
    "path": "Blog.IdentityServer/SameSiteHandlingExtensions.cs",
    "chars": 2953,
    "preview": "using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.DependencyInjection;\n\nna"
  },
  {
    "path": "Blog.IdentityServer/SeedData.cs",
    "chars": 11355,
    "preview": "using System;\nusing System.Linq;\nusing System.Security.Claims;\nusing IdentityModel;\nusing IdentityServer4.EntityFramewo"
  },
  {
    "path": "Blog.IdentityServer/Startup.cs",
    "chars": 9879,
    "preview": "using System;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Identity;\nusing Microsoft.EntityFrameworkC"
  },
  {
    "path": "Blog.IdentityServer/Views/Account/AccessDenied.cshtml",
    "chars": 321,
    "preview": "@{\n    ViewData[\"Title\"] = \"Access denied\";\n}\n<br/>\n<header>\n    <div class=\"alert alert-danger\">\n        <h2 class=\"te"
  },
  {
    "path": "Blog.IdentityServer/Views/Account/ConfirmEmail.cshtml",
    "chars": 151,
    "preview": "@{\n    ViewData[\"Title\"] = \"Confirm email\";\n}\n\n<h2>@ViewData[\"Title\"]</h2>\n<div>\n    <p>\n        Thank you for confirmi"
  },
  {
    "path": "Blog.IdentityServer/Views/Account/Edit.cshtml",
    "chars": 1952,
    "preview": "@model EditViewModel\n@{\n    ViewData[\"Title\"] = \"Edit\";\n\n}\n\n<h2>@ViewData[\"Title\"]</h2>\n\n<div class=\"row\">\n    <div cla"
  },
  {
    "path": "Blog.IdentityServer/Views/Account/ForgotPassword.cshtml",
    "chars": 1374,
    "preview": "@model ForgotPasswordViewModel\n@{\n    ViewData[\"Title\"] = \"Forgot your password?\";\n}\n\n<h2>@ViewData[\"Title\"]</h2>\n<h4>E"
  },
  {
    "path": "Blog.IdentityServer/Views/Account/ForgotPasswordConfirmation.cshtml",
    "chars": 137,
    "preview": "@{\n    ViewData[\"Title\"] = \"Forgot password confirmation\";\n}\n\n<h2>@ViewData[\"Title\"]</h2>\n<p>\n    @Html.Raw(ViewBag.Res"
  },
  {
    "path": "Blog.IdentityServer/Views/Account/LoggedOut.cshtml",
    "chars": 1032,
    "preview": "@model LoggedOutViewModel\n\n@{ \n    // set this so the layout rendering sees an anonymous user\n    ViewData[\"signed-out\""
  },
  {
    "path": "Blog.IdentityServer/Views/Account/Login.cshtml",
    "chars": 4355,
    "preview": "@model LoginViewModel\n\n<link href=\"~/css/login_styles.css\" rel=\"stylesheet\" />\n\n<script src=\"~/js/bootstrap-show-passwo"
  },
  {
    "path": "Blog.IdentityServer/Views/Account/Logout.cshtml",
    "chars": 601,
    "preview": "@model LogoutViewModel\n\n<div class=\"logout-page\">\n    <div class=\"page-header\">\n        <h1>Logout</h1>\n    </div>\n\n   "
  },
  {
    "path": "Blog.IdentityServer/Views/Account/My.cshtml",
    "chars": 1784,
    "preview": "@model EditViewModel\n@{\n    ViewData[\"Title\"] = \"个人中心\";\n\n}\n\n<h2>@ViewData[\"Title\"]</h2>\n\n<div class=\"row\">\n    <div cla"
  },
  {
    "path": "Blog.IdentityServer/Views/Account/Register.cshtml",
    "chars": 2576,
    "preview": "@model RegisterViewModel\n@{\n    ViewData[\"Title\"] = \"Register\";\n}\n\n<h2>@ViewData[\"Title\"]</h2>\n\n<div class=\"row\">\n    <"
  },
  {
    "path": "Blog.IdentityServer/Views/Account/ResetPassword.cshtml",
    "chars": 1705,
    "preview": "@model ResetPasswordViewModel\n@{\n    ViewData[\"Title\"] = \"Reset password\";\n}\n\n<h2>@ViewData[\"Title\"]</h2>\n<h4>Reset you"
  },
  {
    "path": "Blog.IdentityServer/Views/Account/ResetPasswordConfirmation.cshtml",
    "chars": 188,
    "preview": "@{\n    ViewData[\"Title\"] = \"Reset password confirmation\";\n}\n\n<h2>@ViewData[\"Title\"]</h2>\n<p>\n    Your password has been"
  },
  {
    "path": "Blog.IdentityServer/Views/Account/RoleEdit.cshtml",
    "chars": 763,
    "preview": "@model RoleEditViewModel\n@{\n    ViewData[\"Title\"] = \"Edit\";\n}\n\n<h2>@ViewData[\"Title\"]</h2>\n\n<div class=\"row\">\n    <div "
  },
  {
    "path": "Blog.IdentityServer/Views/Account/RoleRegister.cshtml",
    "chars": 704,
    "preview": "@model RoleRegisterViewModel\n@{\n    ViewData[\"Title\"] = \"Register\";\n}\n\n<h2>@ViewData[\"Title\"]</h2>\n\n<div class=\"row\">\n "
  },
  {
    "path": "Blog.IdentityServer/Views/Account/Roles.cshtml",
    "chars": 2489,
    "preview": "@model List<Blog.IdentityServer.Models.ApplicationRole>\n@{\n    ViewData[\"Title\"] = \"Roles\";\n}\n<link href=\"~/css/showtip"
  },
  {
    "path": "Blog.IdentityServer/Views/Account/Users.cshtml",
    "chars": 3361,
    "preview": "@model List<Blog.IdentityServer.Models.ApplicationUser>\n@{\n    ViewData[\"Title\"] = \"Users\";\n    int index = 0;\n}\n<link "
  },
  {
    "path": "Blog.IdentityServer/Views/ApiResourcesManager/CreateOrEdit.cshtml",
    "chars": 3491,
    "preview": "\n@{\n    ViewData[\"Title\"] = \"Create\";\n}\n<style>\n    section.todoapp {\n        width: 600px;\n    }\n\n    input.Client-inp"
  },
  {
    "path": "Blog.IdentityServer/Views/ApiResourcesManager/Index.cshtml",
    "chars": 2237,
    "preview": "@model List<IdentityServer4.EntityFramework.Entities.ApiResource>\n@using IdentityServer4.EntityFramework.Mappers\n\n@{\n  "
  },
  {
    "path": "Blog.IdentityServer/Views/ClientsManager/CreateOrEdit.cshtml",
    "chars": 5617,
    "preview": "\n@{\n    ViewData[\"Title\"] = \"Create\";\n}\n<style>\n    section.todoapp {\n    }\n\n    input.Client-input {\n        /*float: "
  },
  {
    "path": "Blog.IdentityServer/Views/ClientsManager/Index.cshtml",
    "chars": 2895,
    "preview": "@model List<IdentityServer4.EntityFramework.Entities.Client>\n@using IdentityServer4.EntityFramework.Mappers\n\n@{\n    Vie"
  },
  {
    "path": "Blog.IdentityServer/Views/Consent/Index.cshtml",
    "chars": 4052,
    "preview": "@model ConsentViewModel\n\n<div class=\"page-consent\">\n    <div class=\"lead\">\n        @if (Model.ClientLogoUrl != null)\n   "
  },
  {
    "path": "Blog.IdentityServer/Views/Device/Success.cshtml",
    "chars": 158,
    "preview": "<div class=\"page-device-success\">\n    <div class=\"lead\">\n        <h1>Success</h1>\n        <p>You have successfully autho"
  },
  {
    "path": "Blog.IdentityServer/Views/Device/UserCodeCapture.cshtml",
    "chars": 663,
    "preview": "@model string\n\n<div class=\"page-device-code\">\n    <div class=\"lead\">\n        <h1>User Code</h1>\n        <p>Please enter "
  },
  {
    "path": "Blog.IdentityServer/Views/Device/UserCodeConfirmation.cshtml",
    "chars": 4274,
    "preview": "@model DeviceAuthorizationViewModel\n\n<div class=\"page-device-confirmation\">\n    <div class=\"lead\">\n        @if (Model.Cl"
  },
  {
    "path": "Blog.IdentityServer/Views/Diagnostics/Index.cshtml",
    "chars": 564,
    "preview": "@model DiagnosticsViewModel\n\n<h1>Authentication cookie</h1>\n\n<h3>Claims</h3>\n<dl>\n    @foreach (var claim in Model.Authe"
  },
  {
    "path": "Blog.IdentityServer/Views/Grants/Config.cshtml",
    "chars": 18690,
    "preview": "\n@{\n    ViewData[\"Title\"] = \"Config\";\n}\n\n\n<div class=\"grants-page\">\n    <div class=\"lead\">\n        <h1>All Grants Type "
  },
  {
    "path": "Blog.IdentityServer/Views/Grants/Index.cshtml",
    "chars": 3263,
    "preview": "@model GrantsViewModel\n\n<div class=\"grants-page\">\n    <div class=\"lead\">\n        <h1>Client Application Permissions</h1"
  },
  {
    "path": "Blog.IdentityServer/Views/Home/Index.cshtml",
    "chars": 3142,
    "preview": "@using IdentityServer4.Extensions\n@{\n    string name = null;\n    if (!true.Equals(ViewData[\"signed-out\"]))\n    {\n      "
  },
  {
    "path": "Blog.IdentityServer/Views/Shared/Error.cshtml",
    "chars": 965,
    "preview": "@model ErrorViewModel\n\n@{\n    var error = Model?.Error?.Error;\n    var errorDescription = Model?.Error?.ErrorDescription"
  },
  {
    "path": "Blog.IdentityServer/Views/Shared/Redirect.cshtml",
    "chars": 269,
    "preview": "@model RedirectViewModel\n\n<h1>You are now being returned to the application.</h1>\n<p>Once complete, you may close this t"
  },
  {
    "path": "Blog.IdentityServer/Views/Shared/_Layout.cshtml",
    "chars": 5206,
    "preview": "@using IdentityServer4.Extensions\n@{\n    string name = null;\n    if (!true.Equals(ViewData[\"signed-out\"]))\n    {\n      "
  },
  {
    "path": "Blog.IdentityServer/Views/Shared/_ScopeListItem.cshtml",
    "chars": 942,
    "preview": "@model ScopeViewModel\n\n<li class=\"list-group-item\">\n    <label>\n        <input class=\"consent-scopecheck\"\n             "
  },
  {
    "path": "Blog.IdentityServer/Views/Shared/_ValidationSummary.cshtml",
    "chars": 193,
    "preview": "@if (ViewContext.ModelState.IsValid == false)\n{\n    <div class=\"alert alert-danger\">\n        <strong>Error</strong>\n   "
  },
  {
    "path": "Blog.IdentityServer/Views/_ViewImports.cshtml",
    "chars": 135,
    "preview": "@using IdentityServer4.Quickstart.UI\n@using IdentityServer4.Quickstart.UI.Device\n@addTagHelper *, Microsoft.AspNetCore."
  },
  {
    "path": "Blog.IdentityServer/Views/_ViewStart.cshtml",
    "chars": 30,
    "preview": "@{\n    Layout = \"_Layout\";\n}\n"
  },
  {
    "path": "Blog.IdentityServer/appsettings.Development.json",
    "chars": 166,
    "preview": "{\n  \"Logging\": {\n    \"IncludeScopes\": false,\n    \"LogLevel\": {\n      \"Default\": \"Debug\",\n      \"System\": \"Information\","
  },
  {
    "path": "Blog.IdentityServer/appsettings.json",
    "chars": 1797,
    "preview": "{\n  \"Logging\": {\n    \"IncludeScopes\": false,\n    \"Debug\": {\n      \"LogLevel\": {\n        \"Default\": \"Warning\"\n      }\n  "
  },
  {
    "path": "Blog.IdentityServer/tempkey.jwk",
    "chars": 1670,
    "preview": "{\"alg\":\"RS256\",\"d\":\"HwqpgH1B1efVFfOh8siXQln2Hc3a5jwNv8iO34ApQ2kIMpirKhvuYbgZfIlroPDEPObOLCXgZWbrQgRi-OkoAPgPbn9vkemT0_au"
  },
  {
    "path": "Blog.IdentityServer/tempkey.rsa",
    "chars": 1679,
    "preview": "{\"KeyId\":\"rNruJfc3LCx8qbpod8foCA\",\"Parameters\":{\"D\":\"V+uOk1wEljBVqO+h+GfgR214tedtVf7rkLArWvAKTdQkBpTxn9xlEqFsCv//FZoVIXy"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/css/login_styles.css",
    "chars": 7965,
    "preview": "\n* {\n    box-sizing: border-box;\n    margin: 0;\n    padding: 0;\n    font-weight: 300;\n}\n\nbody {\n    font-family: 'Source"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/css/showtip.css",
    "chars": 96,
    "preview": ".alert {\n    position: fixed !important;\n    top: 200px !important;\n    left: 50% !important;\n}\n"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/css/site.css",
    "chars": 1420,
    "preview": "body {\n  margin-top: 65px;\n}\n.navbar-header {\n  position: relative;\n  top: -4px;\n}\n.navbar-brand > .icon-banner {\n  pos"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/css/site.less",
    "chars": 1843,
    "preview": "body {\n    margin-top: 65px;\n}\n\n.navbar-header {\n    position: relative;\n    top: -4px;\n}\n\n.navbar-brand > .icon-banner"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/css/web.css",
    "chars": 8552,
    "preview": "/*Common*/\n@media (max-width: 767px) {\n    .menu {\n        text-align: center;\n    }\n\n    .menu-logo {\n        font-size"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/js/Role.js",
    "chars": 451,
    "preview": "var Roleid = '';\n\n$(\".viewbtn\").on(\"click\", function () {\n    Roleid = $(this).data('id');\n\n});\n$(\".deletebutton\").on(\""
  },
  {
    "path": "Blog.IdentityServer/wwwroot/js/User.js",
    "chars": 447,
    "preview": "var userid = '';\n\n$(\".viewbtn\").on(\"click\", function () {\n    userid = $(this).data('id');\n\n});\n$(\".deletebutton\").on(\""
  },
  {
    "path": "Blog.IdentityServer/wwwroot/js/bootstrap-show-password.js",
    "chars": 6723,
    "preview": "/**\n * @author zhixin wen <wenzhixin2010@gmail.com>\n * https://github.com/wenzhixin/bootstrap-show-password\n * version: "
  },
  {
    "path": "Blog.IdentityServer/wwwroot/js/showTip.js",
    "chars": 773,
    "preview": "//tip是提示信息,type:'success'是成功信息,'danger'是失败信息,'info'是普通信息\nfunction ShowTip(tip, type) {\n    var $tip = $('#tip');\n    if"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/js/signin-redirect.js",
    "chars": 100,
    "preview": "window.location.href = document.querySelector(\"meta[http-equiv=refresh]\").getAttribute(\"data-url\");\n"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/js/signout-redirect.js",
    "chars": 167,
    "preview": "window.addEventListener(\"load\", function () {\n    var a = document.querySelector(\"a.PostLogoutRedirectUri\");\n    if (a)"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/bootstrap/css/bootstrap.css",
    "chars": 147463,
    "preview": "/*!\n * Bootstrap v3.3.5 (http://getbootstrap.com)\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://gi"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/bootstrap/js/bootstrap.js",
    "chars": 68890,
    "preview": "/*!\n * Bootstrap v3.3.5 (http://getbootstrap.com)\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under the MIT license"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/.bower.json",
    "chars": 888,
    "preview": "{\n  \"name\": \"jquery-validation\",\n  \"homepage\": \"http://jqueryvalidation.org/\",\n  \"repository\": {\n    \"type\": \"git\",\n    "
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/CONTRIBUTING.md",
    "chars": 3366,
    "preview": "# Contributing to the jQuery Validation Plugin\n\n## Reporting an Issue\n\n1. Make sure the problem you're addressing is rep"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/Gruntfile.js",
    "chars": 4064,
    "preview": "/*jshint node:true*/\nmodule.exports = function(grunt) {\n\n\"use strict\";\n\nvar banner,\n\tumdStart,\n\tumdMiddle,\n\tumdEnd,\n\tumd"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/LICENSE.md",
    "chars": 1094,
    "preview": "The MIT License (MIT)\n=====================\n\nCopyright Jörn Zaefferer\n\nPermission is hereby granted, free of charge, to "
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/README.md",
    "chars": 2849,
    "preview": "[jQuery Validation Plugin](http://jqueryvalidation.org/) - Form validation made easy\n================================\n\n["
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/bower.json",
    "chars": 565,
    "preview": "{\n\t\"name\": \"jquery-validation\",\n\t\"homepage\": \"http://jqueryvalidation.org/\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": "
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/changelog.md",
    "chars": 40707,
    "preview": "1.14.0 / 2015-06-30\n==================\n\n## Core\n  * Remove unused removeAttrs method\n  * Replace regex for url method\n  "
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/dist/additional-methods.js",
    "chars": 36839,
    "preview": "/*!\n * jQuery Validation Plugin v1.14.0\n *\n * http://jqueryvalidation.org/\n *\n * Copyright (c) 2015 Jörn Zaefferer\n * Re"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/dist/jquery.validate.js",
    "chars": 42629,
    "preview": "/*!\n * jQuery Validation Plugin v1.14.0\n *\n * http://jqueryvalidation.org/\n *\n * Copyright (c) 2015 Jörn Zaefferer\n * Re"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/package.json",
    "chars": 1292,
    "preview": "{\n\t\"name\": \"jquery-validation\",\n\t\"title\": \"jQuery Validation Plugin\",\n\t\"description\": \"Client-side form validation made "
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/accept.js",
    "chars": 1170,
    "preview": "// Accept a value from a file input based on a required mimetype\n$.validator.addMethod(\"accept\", function(value, element"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/additional.js",
    "chars": 1015,
    "preview": "(function() {\n\n\tfunction stripHtml(value) {\n\t\t// remove html tags and space chars\n\t\treturn value.replace(/<.[^<>]*?>/g, "
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/alphanumeric.js",
    "chars": 174,
    "preview": "$.validator.addMethod(\"alphanumeric\", function(value, element) {\n\treturn this.optional(element) || /^\\w+$/i.test(value);"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/bankaccountNL.js",
    "chars": 734,
    "preview": "/*\n * Dutch bank account numbers (not 'giro' numbers) have 9 digits\n * and pass the '11 check'.\n * We accept the notatio"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/bankorgiroaccountNL.js",
    "chars": 300,
    "preview": "$.validator.addMethod(\"bankorgiroaccountNL\", function(value, element) {\n\treturn this.optional(element) ||\n\t\t\t($.validato"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/bic.js",
    "chars": 984,
    "preview": "/**\n * BIC is the business identifier code (ISO 9362). This BIC check is not a guarantee for authenticity.\n *\n * BIC pat"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/cifES.js",
    "chars": 2032,
    "preview": "/*\n * Código de identificación fiscal ( CIF ) is the tax identification code for Spanish legal entities\n * Further rules"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/cpfBR.js",
    "chars": 1632,
    "preview": "/*\n * Brazillian CPF number (Cadastrado de Pessoas Físicas) is the equivalent of a Brazilian tax registration number.\n *"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/creditcardtypes.js",
    "chars": 1888,
    "preview": "/* NOTICE: Modified version of Castle.Components.Validator.CreditCardValidator\n * Redistributed under the the Apache Lic"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/currency.js",
    "chars": 1303,
    "preview": "/**\n * Validates currencies with any given symbols by @jameslouiz\n * Symbols can be optional or required. Symbols requir"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/dateFA.js",
    "chars": 250,
    "preview": "$.validator.addMethod(\"dateFA\", function(value, element) {\n\treturn this.optional(element) || /^[1-4]\\d{3}\\/((0?[1-6]\\/(("
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/dateITA.js",
    "chars": 1162,
    "preview": "/**\n * Return true, if the value is a valid date, also making this formal check dd/mm/yyyy.\n *\n * @example $.validator.m"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/dateNL.js",
    "chars": 211,
    "preview": "$.validator.addMethod(\"dateNL\", function(value, element) {\n\treturn this.optional(element) || /^(0?[1-9]|[12]\\d|3[01])[\\."
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/extension.js",
    "chars": 417,
    "preview": "// Older \"accept\" file extension method. Old docs: http://docs.jquery.com/Plugins/Validation/Methods/accept\n$.validator."
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/giroaccountNL.js",
    "chars": 253,
    "preview": "/**\n * Dutch giro account numbers (not bank numbers) have max 7 digits\n */\n$.validator.addMethod(\"giroaccountNL\", functi"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/iban.js",
    "chars": 3548,
    "preview": "/**\n * IBAN is the international bank account number.\n * It has a country - specific format, that is checked here too\n *"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/integer.js",
    "chars": 173,
    "preview": "$.validator.addMethod(\"integer\", function(value, element) {\n\treturn this.optional(element) || /^-?\\d+$/.test(value);\n}, "
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/ipv4.js",
    "chars": 275,
    "preview": "$.validator.addMethod(\"ipv4\", function(value, element) {\n\treturn this.optional(element) || /^(25[0-5]|2[0-4]\\d|[01]?\\d\\d"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/ipv6.js",
    "chars": 1016,
    "preview": "$.validator.addMethod(\"ipv6\", function(value, element) {\n\treturn this.optional(element) || /^((([0-9A-Fa-f]{1,4}:){7}[0-"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/lettersonly.js",
    "chars": 150,
    "preview": "$.validator.addMethod(\"lettersonly\", function(value, element) {\n\treturn this.optional(element) || /^[a-z]+$/i.test(value"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/letterswithbasicpunc.js",
    "chars": 184,
    "preview": "$.validator.addMethod(\"letterswithbasicpunc\", function(value, element) {\n\treturn this.optional(element) || /^[a-z\\-.,()'"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/mobileNL.js",
    "chars": 238,
    "preview": "$.validator.addMethod(\"mobileNL\", function(value, element) {\n\treturn this.optional(element) || /^((\\+|00(\\s|\\s?\\-\\s?)?)3"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/mobileUK.js",
    "chars": 936,
    "preview": "/* For UK phone functions, do the following server side processing:\n * Compare original input with this RegEx pattern:\n "
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/nieES.js",
    "chars": 762,
    "preview": "/*\n * The número de identidad de extranjero ( NIE )is a code used to identify the non-nationals in Spain\n */\n$.validator"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/nifES.js",
    "chars": 716,
    "preview": "/*\n * The Número de Identificación Fiscal ( NIF ) is the way tax identification used in Spain for individuals\n */\n$.vali"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/notEqualTo.js",
    "chars": 247,
    "preview": "jQuery.validator.addMethod( \"notEqualTo\", function( value, element, param ) {\n\treturn this.optional(element) || !$.valid"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/nowhitespace.js",
    "chars": 150,
    "preview": "$.validator.addMethod(\"nowhitespace\", function(value, element) {\n\treturn this.optional(element) || /^\\S+$/i.test(value);"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/pattern.js",
    "chars": 579,
    "preview": "/**\n* Return true if the field value matches the given format RegExp\n*\n* @example $.validator.methods.pattern(\"AR1004\",e"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/phoneNL.js",
    "chars": 315,
    "preview": "/**\n * Dutch phone numbers have 10 digits (or 11 and start with +31).\n */\n$.validator.addMethod(\"phoneNL\", function(valu"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/phoneUK.js",
    "chars": 1011,
    "preview": "/* For UK phone functions, do the following server side processing:\n * Compare original input with this RegEx pattern:\n "
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/phoneUS.js",
    "chars": 718,
    "preview": "/**\n * matches US phone number format\n *\n * where the area code may not start with 1 and the prefix may not start with 1"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/phonesUK.js",
    "chars": 1064,
    "preview": "/* For UK phone functions, do the following server side processing:\n * Compare original input with this RegEx pattern:\n "
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/postalCodeCA.js",
    "chars": 534,
    "preview": "/**\n * Matches a valid Canadian Postal Code\n *\n * @example jQuery.validator.methods.postalCodeCA( \"H0H 0H0\", element )\n "
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/postalcodeBR.js",
    "chars": 285,
    "preview": "/*\n* Valida CEPs do brasileiros:\n*\n* Formatos aceitos:\n* 99999-999\n* 99.999-999\n* 99999999\n*/\n$.validator.addMethod(\"pos"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/postalcodeIT.js",
    "chars": 201,
    "preview": "/* Matches Italian postcode (CAP) */\n$.validator.addMethod(\"postalcodeIT\", function(value, element) {\n\treturn this.optio"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/postalcodeNL.js",
    "chars": 186,
    "preview": "$.validator.addMethod(\"postalcodeNL\", function(value, element) {\n\treturn this.optional(element) || /^[1-9][0-9]{3}\\s?[a-"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/postcodeUK.js",
    "chars": 486,
    "preview": "// Matches UK postcode. Does not match to UK Channel Islands that have their own postcodes (non standard UK)\n$.validator"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/require_from_group.js",
    "chars": 1411,
    "preview": "/*\n * Lets you say \"at least X inputs that match selector Y must be filled.\"\n *\n * The end result is that neither of the"
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/skip_or_fill_minimum.js",
    "chars": 1667,
    "preview": "/*\n * Lets you say \"either at least X inputs that match selector Y must be filled,\n * OR they must all be skipped (left "
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/statesUS.js",
    "chars": 2345,
    "preview": "/* Validates US States and/or Territories by @jdforsythe\n * Can be case insensitive or require capitalization - default "
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/strippedminlength.js",
    "chars": 259,
    "preview": "// TODO check if value starts with <, otherwise don't try stripping anything\n$.validator.addMethod(\"strippedminlength\", "
  },
  {
    "path": "Blog.IdentityServer/wwwroot/lib/jquery-validation/src/additional/time.js",
    "chars": 203,
    "preview": "$.validator.addMethod(\"time\", function(value, element) {\n\treturn this.optional(element) || /^([01]\\d|2[0-3]|[0-9])(:[0-5"
  }
]

// ... and 77 more files (download for full content)

About this extraction

This page contains the full source code of the anjoy8/Blog.IdentityServer GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 277 files (1.0 MB), approximately 271.9k tokens, and a symbol index with 330 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!