IT教程 ·

受权认证(IdentityServer4)

redis系列-14点的灵异事件

区分

OpenId: Authentication :认证
Oauth: Aurhorize :受权
受权认证(IdentityServer4) IT教程 第1张

  • 输入账号暗码,QQ确认输入了准确的账号暗码能够登录 --->认证
  • 下面须要勾选的复选框(猎取昵称、头像、性别)----->受权

OpenID

当你须要接见A网站的时刻,A网站要求你输入你的OpenId,即可跳转到你的OpenId效劳网站,输入用户名和暗码今后,再调回A网站,则认证胜利。

OAuth2.0

OAuth是一个关于受权的开放收集协定,许可用户让第三方运用接见该用户在在某一网站上的资本,而无需供应用户名和暗码给第三方。

  • 用户翻开客户端今后,客户端要求用户赋予受权。
  • 用户赞同赋予客户端受权。
  • 客户端运用上一步取得的受权,向认证效劳器要求令牌。
  • 认证效劳器对客户端举行认证今后,确认无误,赞同发放令牌。
  • 客户端运用令牌,向资本效劳器要求猎取资本。
  • 资本效劳器确认令牌无误,赞同向客户端开放资本。
    客户端必需获得用户的受权,才猎取令牌。OAuth2.0定义了四种受权体式格局:
  • 受权码形式(authorization code)
  • 简化形式(implicit)
  • 暗码形式(resource owner password credentials)
  • 客户端形式(client credentials)

OpenID --(OpenID Connect) 简称OIDC

OpenID Connect是OpenID的升级版,简称OIDC,是2014年终宣布的开放范例,定义了一种基于OAuth2的可互操纵的体式格局来来供应用户身份认证。在OIDC中,运用程序没必要再为每一个客户端构建差别的协定,而是能够将一个协定供应给多个客户端,它还运用了JOSN署名和加密范例,用来在通报照顾署名和加密的信息,并运用简朴的REST/JSON音讯流来完成,和之前任何一种身份认证协定比拟,开发者都能够轻松的集成。==简朴说 OIDC是在OAuth2.0之上的一个扩大==

ID Tokens
OpenID Connect Id Token是一个署名的JSON Web Token(JWT:RFC7519),它包含一组关于用户身份的声明(claim),如:用户的标识(sub)、颁布令牌的供应程序的标识符(iss)、建立此标识的Client标识(aud),还包含token的有效期以及其他相干的上下文信息
Access Tokens
接见令牌许可接见API资本。 客户端要求接见令牌并将其转发到API。 接见令牌包含有关客户端和用户的信息(假如存在)。 API运用该信息来受权接见其数据。
UserInfo Endpoint
OIDC还供应了一个包含当前用户信息的范例的受庇护的资本。UserInfo Endpoint不是身份认证的一部份,而是供应附加的标识信息,它供应了一组范例化的属性:比方profile、email、phone和address。OIDC中定义了一个迥殊的openidscope,并且是必需的,它包含对Id token和UserInfo Endpoint的接见权限。

IdentityServer4

如今的运用开发屡见不鲜,基于浏览器的网页运用,基于微信的民众号、小程序,基于IOS、Android的App,基于Windows体系的桌面运用和UWP运用等等,这么多品种的运用,就给运用的开发带来的应战,我们除了离别完成各个运用外,我们还要斟酌各个运用之间的交互,通用模块的提炼,个中身份的认证和受权就是每一个运用必不可少的的一部份。而如今的互联网,关于信息平安要求又非常刻薄,所以一套一致的身份认证和受权就至关重要。

IdentityServer4就是如许一个框架,IdentityServer4是为ASP.NET CORE量身定制的完成了OpenId Connect和OAuth2.0协定的认证受权中间件。

JwtBearer 认证

HTTP供应了一套范例的身份考证框架:效劳器能够用来针对客户端的要求发送质询(challenge),客户端依据质询供应身份考证凭据。质询与应对的事情流程以下:效劳器端向客户端返回401(Unauthorized,未受权)状况码,并在WWW-Authenticate头中增添怎样举行考证的信息,个中最少包含有一种质询体式格局。然后客户端能够在要求中增添Authorization头举行考证,其Value为身份考证的凭据信息。

Bearer认证(也叫做令牌认证)是一种HTTP认证计划,个中包含的平安令牌的叫做Bearer Token。因而Bearer认证的中心是Token。那怎样确保Token的平安是重中之重。一种体式格局是运用Https,另一种体式格局就是对Token举行加密署名。而JWT就是一种比较盛行的Token编码体式格局。

JWT(Json Web Token)

Json web token (JWT), 是为了在收集运用环境间通报声明而实行的一种基于JSON的开放范例(RFC 7519)。该token被设想为紧凑且平安的,迥殊适用于分布式站点的单点登录(SSO)场景。JWT的声明平常被用来在身份供应者和效劳供应者间通报被认证的用户身份信息,以便于从资本效劳器猎取资本,也能够增添一些分外的别的营业逻辑所必需的声明信息,该token也可直接被用于认证,也可被加密。

JWT有三部份构成:

. .

Header:由alg和typ构成,alg是algorithm的缩写,typ是type的缩写,指定token的范例。该部份运用Base64Url编码。
Payload:重要用来存储信息,包含种种声明,一样该部份也由BaseURL编码。
Signature:署名,运用效劳器端的密钥举行署名。以确保Token未被改动。

ASP.NET受权认证(OWIN、Katana)

ASP.NET

现有的的asp.net是成熟且功用雄厚的运转时和开发人员编程模子,同时这个框架已整体式,种种差别逻辑的功用单元都严密耦合在System.web.dll程序集合。作为更大的.NET Framework更新周期基本以年为单元。开发团队采纳了几个进化步骤将ASP.NET作为可插进去的一系列组件而不是单一框架。

  1. 为满足Mvc款式的开发需求,ASP.NET MVC宣布,作为自力下载,这使得工程团队能够更频仍的托付更新。
  2. 从动态的,由效劳器生产Web pages转变为经由过程AJAX要求体式格局与后端Web APi通讯。跟着ASP.NETMVC的宣布,构建了ASP.NET WEBAPI,使其不依赖System.Web.dll,其次不依赖IIS等,包含在自定义主机中运转的功用。

    OWIN

    OWIN定义了.NET Web效劳器和Web运用程序之间的范例接口。OWIN接口的目的是星散效劳器和运用程序。

    Katana

    用于Microsoft效劳器和框架的OWIN完成

    上风

  • 可移植
  • 天真采纳模块化构造
  • 轻型、高性能、可缩放

构造

  • HOST(主机):担任运用程序的设置和启动历程,包含初始化Owin Pipeline、运转Server。
  • Server(效劳):现实的HTTP Server。监听HTTP要求,然后将要乞降相应等封装为Owin范例的字典发送到Owin Middleware 管道中。
  • Middleware(中间件):中间件位于效劳和运用程序质检,用来处置惩罚管道中的要求,能够是任何自定义托付的组件。比方:Logger,Web API.
  • Application(运用程序):详细的运用程序代码。

    Owin OAuth

    代码完成

///启动设置
public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        //受权认证
        ConfigAuth(app, container);
        
        app.UseWebApi(config);
        
    }
    private void ConfigAuth(IAppBuilder app,IContainer container)
    {
        app.CreatePerOwinContext(()=> PatternDbContext.Create());
        app.CreatePerOwinContext<ApplicationRoleManagers>(CreateRoleManager);
        app.CreatePerOwinContext<ApplicationUserManagers>(CreateUserManager);

        OAuthAuthorizationServerOptions option = new OAuthAuthorizationServerOptions()
        {

            AllowInsecureHttp = true,
            AuthenticationMode = AuthenticationMode.Active,

            TokenEndpointPath = new PathString("/token"),//猎取 access_token 受权效劳要求地点
            AuthorizeEndpointPath = new PathString("/authorize"), //猎取 authorization_code 受权效劳要求地点
            
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),

            Provider = new OpenAuthorizationServerProvider(), //access_token 相干受权效劳
            AuthorizationCodeProvider = new OpenAuthorizationCodeProvider(), //authorization_code 受权效劳
            //RefreshTokenProvider = new OpenRefreshTokenProvider() ,//refresh_token 受权效劳
            AccessTokenProvider = new OpenAccessTokenProvider()

        };
        //启用受权效劳器,发生token
        app.UseOAuthAuthorizationServer(option);
        //启用受权认证
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
    }
}
public class OpenAuthorizationServerProvider:OAuthAuthorizationServerProvider
{
    /// <summary>
    /// 用户名暗码受权处置惩罚
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        {
                        var userManager = context.OwinContext.GetUserManager<ApplicationUserManagers>();
            var roleManager = context.OwinContext.GetUserManager<ApplicationRoleManagers>();

            context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
            //查询用户是不是存在
            var userModel = new UserModel() { UserName = context.UserName, Password = context.Password };
            var user = await userManager.FindAsync(userModel.UserName,userModel.Password);
            if (user==null)
            {
                context.SetError("invalid_grant", "The user name or password is incorrect");
                return;
            }
            var IpAddress = context.Request.RemoteIpAddress;
            var db = context.OwinContext.Get<PatternDbContext>();
            var result = db.Set<DeviceAddress>().FirstOrDefault(d => d.Address == IpAddress);

            if (result == null)
            {
                context.SetError("invalid_client", IpAddress + "client is not valid");
                return;

            }
           //查询用户角色
            var roles = await userManager.GetRolesAsync(user.Id);

            //组装用户权限等声明信息
            var identity = new ClaimsIdentity(context.Options.AuthenticationType);
            identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
            identity.AddClaim(new Claim("userName", context.UserName));
            foreach (var role in roles)
            {
                var roleTemp = await roleManager.FindByNameAsync(role);//猎取角色对应的权限
                foreach (var permission in roleTemp.Permissions)
                {
                    identity.AddClaim(new Claim("Permission", permission.Info));
                }
                identity.AddClaim(new Claim(ClaimTypes.Role, role));
            }
            //分外显现属性
            var props = new AuthenticationProperties(new Dictionary<string, string>
            {
                //{"as:client_id",context.ClientId??string.Empty },
                {"userName",context.UserName },
                 {"userId",user.Id }
            });

            var ticket = new AuthenticationTicket(identity, props);
            //校验生成token
            context.Validated(ticket);
        }
}
///自定义受权
public class MyAuthorizeAttribute:AuthorizeAttribute
{
    protected override bool IsAuthorized(HttpActionContext actionContext)
    {
        //猎取用户对象
        IPrincipal principal = actionContext.ControllerContext.RequestContext.Principal;
        if (principal == null)
        {
            var token = actionContext.Request.Headers.Authorization.Parameter;
            using (PatternDbContext db=new PatternDbContext())
            {
                var tokenStr = db.LoginStates.FirstOrDefault(t => t.TokenStr == token);
                if (tokenStr != null)
                {
                    tokenStr.IsOnline = false;
                    tokenStr.LogoutDate = DateTime.Now;
                    db.SaveChanges();
                }
            }

            return false;
        }
        //猎取权限声明
        var claims = (principal.Identity as ClaimsIdentity).Claims.Where(d=>d.Type=="Permission").Select(d=>d.Value);
        if (claims != null)
        {
            if((Permission!=null)&&! claims.Contains(Permission,StringComparer.OrdinalIgnoreCase))
            {
                return false;
            }
        }
        else
        {
            return false;
        }

        return base.IsAuthorized(actionContext);
    }
}
   

ASP.NET CORE受权认证(IdentityServer4)

认证效劳器

    //注册认证效劳器
    services.AddIdentityServer()
        .AddDeveloperSigningCredential()
        .AddMongoRepository()
        //.AddMongoDbForAspIdentity<ApplicationUser, ApplicationRole>(Configuration)
        .AddClients()
        .AddPersistedGrants()
        .AddIdentityApiResources()
        .AddAspNetIdentity<ApplicationUser>()                
        .AddResourceOwnerValidator<CustomResourceOwnerPasswordValidtor<ApplicationUser,ApplicationRole>>()
        .AddProfileService<CusromProfileService<ApplicationUser>>()
        .AddCorsPolicyService< CorsPolicyService>()              
        ;

资本效劳

//增添认证
services.AddAuthentication(opt =>
{    
    opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    
})
.AddCookie("Cookies")
.AddJwtBearer("Bearer", options =>
{
    options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
    {

        IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("secret")),
        ValidateLifetime = true,
    };
    var configUrl = new ConfigurationBuilder().AddJsonFile("host.json", false, true).Build()["urls"];
    //var url = Configuration["urls"];
    options.Authority = configUrl;
    options.RequireHttpsMetadata = false;
    options.Audience = "KnowBaseApi";

});  

MVC客户端

services.AddAuthentication(options =>
    {
        options.DefaultScheme = "Cookies";
        options.DefaultChallengeScheme = "oidc";
        
    })
    .AddCookie("Cookies",opt=>
    {
        opt.LoginPath = "/Login";
    })
    .AddOpenIdConnect("oidc", options =>
    {
        options.SignInScheme = "Cookies";
        
        options.Authority = "http://10.53.28.168:5010";
        options.RequireHttpsMetadata = false;
        options.CallbackPath = "/home";
        options.ClientId = "AntennaKnowbaseApi";
        options.ClientSecret = "secret";
        options.ResponseType = "code id_token";

        options.SaveTokens = true;
        options.GetClaimsFromUserInfoEndpoint = true;

        options.Scope.Add("api1");
        options.Scope.Add("offline_access");
        options.Scope.Add("profile");

        //options.ClaimActions.MapJsonKey("website", "website");
    });

从实战角度超级详解中大型企业微服务化的六大核心关键技术

参与评论