• IdentityServer4-HybridAndClientCredentials


    一、服务器

    Client设置:

     1  new Client
     2                 {
     3                     ClientId = "mvc1",
     4                     ClientName = "后台管理MVC客户端",
     5                     ClientSecrets = { new Secret("mvc1".Sha256()) },
     6 
     7                     AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
     8                     AllowOfflineAccess = true,
     9                     RequireConsent = false,
    10                     RedirectUris = { $"{ClientUrl}/signin-oidc",$"{LocalClientUrl}/signin-oidc"},
    11                     PostLogoutRedirectUris = { $"{ClientUrl}/signout-callback-oidc",$"{LocalClientUrl}/signout-callback-oidc"},
    12 
    13                     AllowedScopes =
    14                     {
    15                         IdentityServerConstants.StandardScopes.OpenId,
    16                         IdentityServerConstants.StandardScopes.Profile,
    17                         "IdServerAdmin_API"
    18                     },
    19 
    20                     AlwaysIncludeUserClaimsInIdToken = true
    21                 }

    Startup.cs:

            /// <summary>
            /// 设置认证服务器
            /// </summary>
            /// <param name="services"></param>
            private void SetIdentityServer(IServiceCollection services)
            {
                #region 认证服务器
                var ServerUrl = Configuration.GetSection("AppSetting:ServerUrl").Value;
                var connectionString = Configuration.GetSection("AppSetting:ConnectionString").Value;
    
                //配置AccessToken的加密证书
                var rsa = new RSACryptoServiceProvider();
                //从配置文件获取加密证书
                rsa.ImportCspBlob(Convert.FromBase64String(Configuration["AppSetting:SigningCredential"]));
                var idServer = services.AddIdentityServer(options => {
                    options.IssuerUri = ServerUrl;
                    options.PublicOrigin = ServerUrl;
    
                    options.Discovery.ShowApiScopes = true;
                    options.Discovery.ShowClaims = true;
    
                    options.Events.RaiseSuccessEvents = true;
                    options.Events.RaiseFailureEvents = true;
                    options.Events.RaiseErrorEvents = true;
    
                });
                //设置加密证书
                idServer.AddSigningCredential(new RsaSecurityKey(rsa));
                idServer.AddInMemoryApiResources(Config.GetApiResources());
                idServer.AddInMemoryIdentityResources(Config.GetIdentityResources());
                idServer.AddInMemoryClients(Config.GetClients());
    
                services.AddTransient<IMyUserStore, MyUserStore>();
                services.AddTransient<IProfileService, MyProfile>();
                services.AddTransient<IResourceOwnerPasswordValidator, MyUserValidator>();
                
                #endregion
            }
    

      

     1 public class MyProfile : IProfileService
     2     {
     3         private readonly IMyUserStore _myUserStore;
     4         public MyProfile(IMyUserStore myUserStore)
     5         {
     6             _myUserStore = myUserStore;
     7         }
     8 
     9         public Task GetProfileDataAsync(ProfileDataRequestContext context)
    10         {
    11             var subjectId = context.Subject.GetSubjectId();
    12             var user = _myUserStore.GetUserById(subjectId);
    13 
    14             
    15 
    16             var claims = new List<Claim>
    17             {
    18                 new Claim("role",  user.Role),
    19                 new Claim("userguid", user.SubjectId),
    20                 new Claim("abc", "这是自定义的值。……。。…。……。……")
    21             };
    22 
    23             var q = context.RequestedClaimTypes;
    24             context.AddRequestedClaims(claims);
    25             context.IssuedClaims.AddRange(claims);
    26 
    27             return Task.FromResult(0);
    28         }
    29 
    30         public Task IsActiveAsync(IsActiveContext context)
    31         {
    32             var user = _myUserStore.GetUserById(context.Subject.GetSubjectId());
    33             context.IsActive = (user != null);
    34 
    35             return Task.FromResult(0);
    36         }
    37     }
     1 public interface IMyUserStore
     2     {
     3         JUser Find(string username, string userpass);
     4         JUser GetUserById(string subjectId);
     5     }
     6 
     7     public class MyUserStore : IMyUserStore
     8     {
     9         readonly IOptions<AppSetting> _options;
    10         readonly IMemoryCache _memoryCache;
    11 
    12         private const string CACHENAME = "MyUserStore";
    13 
    14         public MyUserStore(IOptions<AppSetting> options, IMemoryCache m_memoryCache)
    15         {
    16             _options = options;
    17             _memoryCache = m_memoryCache;
    18         }
    19 
    20         public List<JUser> GetList(bool reload=true)
    21         {
    22             if (reload)
    23             {
    24                 _memoryCache.Remove(CACHENAME);
    25             }
    26 
    27             List<JUser> list;
    28             if (!_memoryCache.TryGetValue(CACHENAME, out list)){
    29                 using(MySqlConnection conn = new MySqlConnection(_options.Value.ConnectionString))
    30                 {
    31                     list = conn.Query<JUser>("select * from juser").ToList();
    32 
    33                     //添加超级用户
    34                     JUser jc = new JUser()
    35                     {
    36                         UserName = _options.Value.SuperUserName,
    37                         UserPass = StringHelper.GetMd5(_options.Value.SuperPassword),
    38                         SubjectId = "a36005e2-5984-41f5-aa91-8e93b479d88e",
    39                         Role = "IdServerAdmin"
    40                     };
    41 
    42                     list.Add(jc);
    43                 }
    44                 _memoryCache.Set(CACHENAME, list);
    45             }
    46             return list;
    47         }
    48 
    49 
    50 
    51         public JUser Find(string username, string userpass)
    52         {
    53             var list = GetList();
    54             return list.SingleOrDefault(p => p.UserName == username && p.UserPass == StringHelper.GetMd5(userpass));
    55         }
    56 
    57         public JUser GetUserById(string subjectId)
    58         {
    59             var list = GetList();
    60             return list.SingleOrDefault(p => p.SubjectId == subjectId);
    61         }
     1 public class MyUserValidator : IResourceOwnerPasswordValidator
     2     {
     3         readonly IMyUserStore _myUserStore;
     4 
     5         public MyUserValidator(IMyUserStore myUserStore)
     6         {
     7             _myUserStore = myUserStore;
     8         }
     9 
    10         public Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
    11         {
    12             var q = _myUserStore.Find(context.UserName, context.Password);
    13 
    14             if (q != null)
    15             {
    16                 //验证成功
    17                 //使用subject可用于在资源服务器区分用户身份等等
    18                 //获取:资源服务器通过User.Claims.Where(l => l.Type == "sub").FirstOrDefault();
    19                 var claims = new List<Claim>();
    20                 claims.Add(new Claim("role", q.Role));
    21                 claims.Add(new Claim("userguid", q.SubjectId));
    22 
    23                 context.Result = new GrantValidationResult(subject: $"{q.SubjectId}", authenticationMethod: "custom", claims: claims.AsEnumerable());
    24             }
    25             else
    26             {
    27                 //验证失败
    28                 context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "无效的用户凭证");
    29             }
    30             return Task.FromResult(0);
    31         }
    32     }

    二、客户端:

     1  /// <summary>
     2         /// 设置认证客户端
     3         /// </summary>
     4         /// <param name="services"></param>
     5         private void SetIdentityClient(IServiceCollection services)
     6         {
     7             var ServerUrl = Configuration.GetSection("AppSetting:ServerUrl").Value;
     8             var client_id = Configuration.GetSection("AppSetting:SuperClientId").Value;
     9             var cient_secret = Configuration.GetSection("AppSetting:SuperClientSecret").Value;
    10 
    11             //services.Configure<MvcOptions>(options =>
    12             //{
    13             //    // Set LocalTest:skipSSL to true to skip SSL requrement in 
    14             //    // debug mode. This is useful when not using Visual Studio.
    15             //    options.Filters.Add(new RequireHttpsAttribute());
    16             //});
    17 
    18             JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
    19 
    20             var idClient = services.AddAuthentication(options =>
    21             {
    22                 options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    23                 options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
    24             })
    25             .AddCookie()
    26             .AddOpenIdConnect(options =>
    27             {
    28                 options.SignOutScheme = OpenIdConnectDefaults.AuthenticationScheme;
    29                 options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; // cookie middle setup above
    30                 options.Authority = ServerUrl; // 认证服务器
    31                 options.RequireHttpsMetadata = true; // SSL Https模式 
    32                 options.ClientId = client_id; // 客户端(位于认证服务器)
    33                 options.ClientSecret = cient_secret;  // 客户端(位于认证服务器)
    34                 options.ResponseType = "code id_token"; // means Hybrid flow (id + access token)
    35 
    36                 options.GetClaimsFromUserInfoEndpoint = false;
    37                 options.SaveTokens = true;
    38                 options.TokenValidationParameters = new TokenValidationParameters
    39                 {
    40                     NameClaimType = "name",
    41                     RoleClaimType = "role"
    42                 };
    43 
    44                 options.Scope.Clear();
    45                 options.Scope.Add("openid");
    46                 options.Scope.Add("profile");
    47                 options.Scope.Add("IdServerAdmin_API");
    48 
    49                 options.Events = new OpenIdConnectEvents()
    50                 {
    51                     OnMessageReceived = (context) =>
    52                     {
    53                         return Task.FromResult(0);
    54                     },
    55 
    56                     OnUserInformationReceived = (context) =>
    57                     {
    58                         return Task.FromResult(0);
    59                     },
    60                     OnRedirectToIdentityProvider = (context) =>
    61                     {
    62                         //设置重定向地址,解决生产环境nginx+https访问,还是有问题。。。。。。。
    63                         context.Properties.RedirectUri = $"{ClientUrl}/signin-oidc";
    64                         //context.ProtocolMessage.RedirectUri = $"{ClientUrl}/signin-oidc";
    65                         return Task.FromResult(0);
    66                     },
    67 
    68                     OnTokenValidated = (context) =>
    69                     {
    70                         //context.Properties.RedirectUri = $"{ClientUrl}/signin-oidc";
    71                         return Task.FromResult(0);
    72                     },
    73                 };
    74             });
    75         }
  • 相关阅读:
    Fiddler配置代理hosts的方法
    Android利用Fiddler进行网络数据抓包
    Android键盘面板冲突 布局闪动处理方案
    View的三次measure,两次layout和一次draw
    jquery.fly.min.js 拋物插件
    js刷新页面方法大全
    Console命令详解,让调试js代码变得更简单
    div中的内容垂直居中的五种方法
    Struts2之i18N国际化
    maven阿里云中央仓库
  • 原文地址:https://www.cnblogs.com/YrRoom/p/7747212.html
Copyright © 2020-2023  润新知