新文章 网摘 文章 随笔 日记

实践使用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;
        }


    }
}

 

posted @ 2020-07-23 14:51  岭南春  阅读(107)  评论(0编辑  收藏  举报