区别OpenId: Authentication :认证
OpenID当你需要访问A网站的时候,A网站要求你输入你的OpenId,即可跳转到你的OpenId服务网站,输入用户名和密码之后,再调回A网站,则认证成功。 OAuth2.0OAuth是一个关于授权的开放网络协议,允许用户让第三方应用访问该用户在在某一网站上的资源,而无需提供用户名和密码给第三方。
OpenID --(OpenID Connect) 简称OIDCOpenID Connect是OpenID的升级版,简称OIDC,是2014年初发布的开放标准,定义了一种基于OAuth2的可互操作的方式来来提供用户身份认证。在OIDC中,应用程序不必再为每个客户端构建不同的协议,而是可以将一个协议提供给多个客户端,它还使用了JOSN签名和加密规范,用来在传递携带签名和加密的信息,并使用简单的REST/JSON消息流来实现,和之前任何一种身份认证协议相比,开发者都可以轻松的集成。简单说 OIDC是在OAuth2.0之上的一个扩展 ID Tokens IdentityServer4现在的应用开发层出不穷,基于浏览器的网页应用,基于微信的公众号、小程序,基于IOS、Android的App,基于Windows系统的桌面应用和UWP应用等等,这么多种类的应用,就给应用的开发带来的挑战,我们除了分别实现各个应用外,我们还要考虑各个应用之间的交互,通用模块的提炼,其中身份的认证和授权就是每个应用必不可少的的一部分。而现在的互联网,对于信息安全要求又十分苛刻,所以一套统一的身份认证和授权就至关重要。
JwtBearer 认证
Bearer认证(也叫做令牌认证)是一种HTTP认证方案,其中包含的安全令牌的叫做Bearer Token。因此Bearer认证的核心是Token。那如何确保Token的安全是重中之重。一种方式是使用Https,另一种方式就是对Token进行加密签名。而JWT就是一种比较流行的Token编码方式。 JWT(Json Web Token)
JWT有三部分组成:
Header:由alg和typ组成,alg是algorithm的缩写,typ是type的缩写,指定token的类型。该部分使用Base64Url编码。 ASP.NET授权认证(OWIN、Katana)ASP.NET现有的的asp.net是成熟且功能丰富的运行时和开发人员编程模型,同时这个框架已整体式,各种不同逻辑的功能单元都紧密耦合在System.web.dll程序集中。作为更大的.NET Framework更新周期基本以年为单位。开发团队采用了几个进化步骤将ASP.NET作为可插入的一系列组件而不是单一框架。
OWINOWIN定义了.NET Web服务器和Web应用程序之间的标准接口。OWIN接口的目标是分离服务器和应用程序。 Katana用于Microsoft服务器和框架的OWIN实现 优势
结构
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"); }); |
|