IdentityServer4 保护.net framework webapi

一、IS4服务器配置

1、新建一个Asp.net  Core MVC程序,模板选择 Empty 

2、Nuget添加 IdentityServer4,我这里添加的是2.5.3

3、添加Config文件,配置clients和scopes等信息,需要持久化配置的可以看 https://www.cnblogs.com/fengchao1000/p/10184921.html

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()
            };
        }

        public static IEnumerable<ApiResource> GetApis()
        {
            return new List<ApiResource>
            {
                new ApiResource("FrameworkAPI",new List<string>(){JwtClaimTypes.Subject})
            };
        }

        public static IEnumerable<Client> GetClients()
        {
            return new List<Client>
            { 
                
                //Implicit模式Client配置,适用于SPA
                new Client
                {
                    ClientId = "Test",
                    ClientName = "Test",
                    AllowedGrantTypes = GrantTypes.Implicit,
                    AllowAccessTokensViaBrowser = true,
                    AccessTokenLifetime = 60*60,
                    AccessTokenType = AccessTokenType.Jwt,
                    RedirectUris =
                    {
                        "https://localhost:5003/signin-callback.html",
                        "https://localhost:5003/silent-callback.html"
                    },
                    PostLogoutRedirectUris = { "https://localhost:5003" },
                    AllowedCorsOrigins = { "https://localhost:5003" },
                    RequireConsent = false,
                    AllowedScopes =
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        "FrameworkAPI"//对应webapi里面的scope配置
                    }
                },
                //ResourceOwnerPassword模式Client配置,适用于App、webform
                new Client
                {
                    ClientId = "App",
                    ClientName = "App",
                    ClientSecrets = { new Secret("123456".Sha256()) },
                    AccessTokenLifetime = 60*60,//单位s
                    AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
                    SlidingRefreshTokenLifetime =  2592000,
                    AllowOfflineAccess = true,
                    AllowedScopes = new List<string>
                    {
                        "FrameworkAPI",//对应webapi里面的scope配置
                        StandardScopes.OfflineAccess,
                        StandardScopes.OpenId,
                        StandardScopes.Profile
                    }
                }

            };
        }  
    }

4、添加ProfileService文件,用于自定义登录返回信息

/// <summary>
    /// 自定义用户登录返回的信息claims
    /// </summary>
    public class ProfileService : IProfileService
    {
        private readonly ILogger logger;

        public ProfileService(ILogger<ProfileService> logger)
        {
            this.logger = logger;
        }

        public async Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            try
            {
                var claims = context.Subject.Claims.ToList();

                context.IssuedClaims = claims.ToList();
            }
            catch (Exception ex)
            {
                logger.LogError(ex.ToString());
            }
        }

        public async Task IsActiveAsync(IsActiveContext context)
        {
            context.IsActive = true;
        }
    }

5、添加ResourceOwnerPasswordValidator文件,在ResourceOwnerPassword模式下用于自定义登录验证

/// <summary>
    ///ResourceOwnerPassword模式下用于自定义登录验证 
    /// </summary>
    public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
    {
        private readonly IConfiguration config;

        public ResourceOwnerPasswordValidator(IConfiguration config)
        {
            this.config = config;
        }

        public Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
        {
            //根据context.UserName和context.Password与数据库的数据做校验,判断是否合法
            if (context.UserName == "test" && context.Password == "test")
            {
                context.Result = new GrantValidationResult(
                 subject: context.UserName,
                 authenticationMethod: OidcConstants.AuthenticationMethods.Password);
            }
            else
            {
                //验证失败
                context.Result = new GrantValidationResult(
                    TokenRequestErrors.InvalidGrant,
                    "invalid custom credential"
                    );
            }
            return Task.FromResult(0);
        }
    }

6、在 Startup 配置IdentityServer

public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {  
            services.AddIdentityServer()
                   //配置证书
                   .AddDeveloperSigningCredential()
                   //配置API资源
                   .AddInMemoryApiResources(Config.GetApis())
                   //配置身份资源
                   .AddInMemoryIdentityResources(Config.GetIdentityResources())
                   //预置Client
                   .AddInMemoryClients(Config.GetClients())
                   .AddProfileService<ProfileService>()
                   .AddResourceOwnerValidator<ResourceOwnerPasswordValidator>();

            services.AddAuthentication()
            .AddCookie(options =>
            {
                options.ExpireTimeSpan = System.TimeSpan.FromMinutes(30);
                options.SlidingExpiration = true;
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseIdentityServer();//IdentityServer4中间件
              
            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("IdentityServer4");
            });
        }
    }

到这里我们IdentityServer4服务端已经搭建好了,我们用postman测试下,这里调用的是ResourceOwnerPassword模式

 二、.net framework webapi 配置

1、新建一个 .net framework webapi 程序

 \

2、由于webapi是.net Framework版本的,所以我们需要引用 IdentityServer3.AccessTokenValidation 作为api端token的验证组件。

Nuget添加:

IdentityServer3.AccessTokenValidation    

IdentityModel   

Microsoft.Owin.Host.SystemWeb 

3、添加一个 Owin Startup.cs ,最好是用现有的startup类,而不要自己去新建一个类,然后修改名称。

4、在Startup中配置 IdentityServer AccessToken 验证参数

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        { 
            app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
            {
                Authority = "http://localhost:62527/",
                RequiredScopes = new[] { "FrameworkAPI" },//对应Client中配置的AllowedScopes和ApiResource

                DelayLoadMetadata = true
            });

        }
    }

5、在 WebAPIConfig 中加入 config.Filters.Add(new AuthorizeAttribute()) 来启用授权验证

config.Filters.Add(new AuthorizeAttribute());

 6、添加TestController

    public class TestController : ApiController 
    {  
        public IHttpActionResult Get()
        {  
            var user = User as ClaimsPrincipal;

            var claims = from c in user.Claims
                         select new
                         {
                             type = c.Type,
                             value = c.Value
                         };

            return Json(claims);
        }  
    }

最后项目结构如下:

三、测试

我们的服务端和webapi都已经配置好了,我们用postman测试下

1、直接访问api地址 http://localhost:44387/test ,不加入token ,得到如下结果,返回401

 2、加入token ,验证通过,返回200

猜你喜欢

转载自www.cnblogs.com/fengchao1000/p/11453976.html