实践使用IdentityServer3
服务端:
using System; using System.Configuration; using System.Security.Cryptography.X509Certificates; using IdentityServer3.Core.Configuration; using IdentityServer3.Core.Services; using IdentityServer3.Sugar.Auth.Repositories; using Microsoft.Owin; using Owin; using Phoenix.Common.Infrastructure.Sugars; using Phoenix.Common.Infrastructure.Ado; [assembly: OwinStartup(typeof(IdentityServer3.Sugar.Auth.Startup))] namespace IdentityServer3.Sugar.Auth { public class Startup { public void Configuration(IAppBuilder app) { //数据库连接配置 var dapperServiceOptions = new DbConfig(SqlSugarRepository.DbType.SqlServer, "Sample.Idsvr"); var userRepository = new UserRepository(dapperServiceOptions,new RbacService(new SqlDbHelper("SparePartsOracleConn") )); var factory = new IdentityServerServiceFactory(); //factory.ViewService = new Registration<IViewService, IdentityServer3.Dapper.Sample.Auth.Services.IdSvrMvcViewService<LoginController>>(); //factory.ViewService = new Registration<IViewService, CustomViewService>(); //注册配置项 factory.RegisterConfigurationServices(dapperServiceOptions); //注册操作配置 factory.RegisterOperationalServices(dapperServiceOptions); //注册用户服务 factory.UserService = new Registration<IUserService>(typeof(SampleUserService)); //注册用户仓储 factory.Register(new Registration<IUserRepository>(userRepository)); //证书公钥 var certificate = Convert.FromBase64String(ConfigurationManager.AppSettings.Get("SigningCertificate")); //证书私钥 var password = ConfigurationManager.AppSettings.Get("SigningCertificatePassword"); var options = new IdentityServerOptions { SiteName = "登錄中心", SigningCertificate = new X509Certificate2(certificate, password), Factory = factory, RequireSsl = false,// DO NOT DO THIS, }; app.UseIdentityServer(options); } } }
客户端:
using System; using System.Globalization; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using IdentityModel.Client; using Microsoft.IdentityModel.Protocols; using Microsoft.Owin; using Microsoft.Owin.Security; using Microsoft.Owin.Security.Cookies; using Microsoft.Owin.Security.OpenIdConnect; using Owin; [assembly: OwinStartup(typeof(IdentityMvcClient.Startup))] namespace IdentityMvcClient { public partial class Startup { private const string IdServBaseUri = "http://localhost:63743"; private const string UserInfoEndpoint = IdServBaseUri + @"/connect/userinfo/"; //private const string TokenEndpoint = IdServBaseUri + @"/connect/token/"; private const string ClientId = "mvc"; //Client 要对应 private const string ClientUri = @"http://localhost:56666/"; private const string ClientSecret = "21B5F798-BE55-42BC-8AA8-0025B903DC3B"; public void Configuration(IAppBuilder app) { app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = "Cookies", }); app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions { Authority = IdServBaseUri, //这里写你idrserver的地址 ClientId = ClientId, //Client 要对应 Scope = "openid profile offline_access", //Client 要对应 RedirectUri = ClientUri, //登陆成功后的跳转地址,要对应 PostLogoutRedirectUri = ClientUri, //如上 ClientSecret = ClientSecret, ResponseType = "code id_token token", //参考配置说明 还有授权码 code SignInAsAuthenticationType = "Cookies", Notifications = new OpenIdConnectAuthenticationNotifications { AuthorizationCodeReceived = async notification => { var userInfoClient = new UserInfoClient(UserInfoEndpoint); var userInfoResponse = await userInfoClient.GetAsync(notification.ProtocolMessage.AccessToken); if (userInfoResponse.IsError) { notification.HandleResponse(); notification.Response.Write("Error retrieving user info."); } var configuration = await notification.Options.ConfigurationManager .GetConfigurationAsync(notification.Request.CallCancelled); var tokenClient = new TokenClient(configuration.TokenEndpoint, notification.Options.ClientId, ClientSecret, AuthenticationStyle.PostValues); var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync( notification.ProtocolMessage.Code, notification.RedirectUri, cancellationToken: notification.Request.CallCancelled); if (tokenResponse.IsError || string.IsNullOrWhiteSpace(tokenResponse.AccessToken) || string.IsNullOrWhiteSpace(tokenResponse.RefreshToken)) { notification.HandleResponse(); notification.Response.Write("Error retrieving tokens."); return; } // create new identity var id = new ClaimsIdentity(notification.AuthenticationTicket.Identity.AuthenticationType); id.AddClaims(userInfoResponse.Claims); id.AddClaim(new Claim("access_token", tokenResponse.AccessToken)); id.AddClaim(new Claim("expires_at", DateTime.UtcNow.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString(CultureInfo.InvariantCulture))); id.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken)); id.AddClaim(new Claim("id_token", notification.ProtocolMessage.IdToken)); //id.AddClaim(new Claim("sid", notification.AuthenticationTicket.Identity.FindFirst("sid").Value)); id.AddClaims(notification.AuthenticationTicket.Identity.Claims); var userId = notification.AuthenticationTicket.Identity.Claims .FirstOrDefault(r => r.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"); if (userId != null) { //防止报not present on the provided ClaimsIdentity.的错误 id.AddClaim(new Claim(ClaimTypes.Name, userId.Value)); } notification.AuthenticationTicket = new AuthenticationTicket( new ClaimsIdentity(id.Claims, notification.AuthenticationTicket.Identity.AuthenticationType), notification.AuthenticationTicket.Properties); }, RedirectToIdentityProvider = n => { // if signing out, add the id_token_hint if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest) { var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token"); if (idTokenHint != null) { n.ProtocolMessage.IdTokenHint = idTokenHint.Value; } } return Task.FromResult(0); } } }); } } }
服务端的:
using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using IdentityServer3.Core.Extensions; using IdentityServer3.Core.Models; using IdentityServer3.Core.Services.Default; using IdentityServer3.Sugar.Auth.Repositories; namespace IdentityServer3.Sugar.Auth { public class SampleUserService : UserServiceBase { private readonly IUserRepository _userRepository; public SampleUserService(IUserRepository userRepository) { _userRepository = userRepository; } public override async Task AuthenticateLocalAsync(LocalAuthenticationContext context) { var user = await _userRepository.GetAsync(context.UserName, context.Password); context.AuthenticateResult = user == null ? new AuthenticateResult("Incorrect credentials") : new AuthenticateResult(user.Username, user.Username); } public override async Task GetProfileDataAsync(ProfileDataRequestContext context) { var sub = context.Subject.GetSubjectId(); var user = _userRepository.GetUserInfo(sub); var claims = user.Privileges.Where(r => r.Controller != null && r.Action != null).Select(r => new Claim(r.Controller, r.Action)); //在此加入用户权限 context.IssuedClaims = claims; } } }