当前位置: 首页 > news >正文

重庆seo网站收录优化抖音网络营销推广方式

重庆seo网站收录优化,抖音网络营销推广方式,国外建站网站,文献综述 php网站开发Ocelot作为网关#xff0c;可以用来作统一验证#xff0c;接上一篇博客Ocelot网关#xff0c;我们继续 前一篇#xff0c;我们创建了OcelotGateway网关项目#xff0c;DemoAAPI项目#xff0c;DemoBAPI项目#xff0c;为了验证用户并分发Token#xff0c;现在还需要添… Ocelot作为网关可以用来作统一验证接上一篇博客Ocelot网关我们继续 前一篇我们创建了OcelotGateway网关项目DemoAAPI项目DemoBAPI项目为了验证用户并分发Token现在还需要添加AuthenticationAPI项目也是asp.net core web api项目整体思路是当用户首次请求Request时web服务网关会判断本请求有无Token并是否正确如果没有或不正确就会反回401 Unauthorized如果请求调用登录正确输入用户名或密码AuthenticationAPI会验证并分发Token当客户端带上Token再次访问web服务时网关就会放过本请求当请求到达web服务时web服务要对本Token进行授权验证如果有访问请求的地址会成功返回应答负责会提示没有权验所以只要具有正确的Token应答返回都是200 OK因为Token正确只是没有权限访问请求的内容。 下面创建最重要的一个项目Ocelot.JWTAuthorizePolicy选.NET Standard的类库作为项目模板创建本项目本项目的作用是为网关项目OcelotGatewayweb服务项目DemoAAPI和DemoBAPI和AuthenticationAPI提供注入JWT或自定义策略的API关于自定义策略可参考http://www.cnblogs.com/axzxs2001/p/7530929.html 本项目中的组成部分 Permission.cs namespace Ocelot.JWTAuthorizePolicy { /// summary /// 用户或角色或其他凭据实体 /// /summary public class Permission { /// summary /// 用户或角色或其他凭据名称 /// /summary public virtual string Name { get; set; } /// summary /// 请求Url /// /summary public virtual string Url { get; set; } } } PermissionRequirement.cs using Microsoft.AspNetCore.Authorization; using Microsoft.IdentityModel.Tokens; using System; using System.Collections.Generic; namespace Ocelot.JWTAuthorizePolicy { /// summary /// 必要参数类 /// /summary public class PermissionRequirement : IAuthorizationRequirement { /// summary /// 无权限action /// /summary public string DeniedAction { get; set; } /// summary /// 认证授权类型 /// /summary public string ClaimType { internal get; set; } /// summary /// 请求路径 /// /summary public string LoginPath { get; set; } /Api/Login; /// summary /// 发行人 /// /summary public string Issuer { get; set; } /// summary /// 订阅人 /// /summary public string Audience { get; set; } /// summary /// 过期时间 /// /summary public TimeSpan Expiration { get; set; } /// summary /// 签名验证 /// /summary public SigningCredentials SigningCredentials { get; set; } /// summary /// 构造 /// /summary /// param namedeniedAction无权限action/param /// param nameuserPermissions用户权限集合/param /// summary /// 构造 /// /summary /// param namedeniedAction拒约请求的url/param  /// param nameclaimType声明类型/param /// param nameissuer发行人/param /// param nameaudience订阅人/param /// param namesigningCredentials签名验证实体/param public PermissionRequirement(string deniedAction, string claimType, string issuer, string audience, SigningCredentials signingCredentials, TimeSpan expiration) { ClaimType claimType; DeniedAction deniedAction;  Issuer issuer; Audience audience; Expiration expiration; SigningCredentials signingCredentials; } } } PermissionHandler.cs using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; namespace Ocelot.JWTAuthorizePolicy { /// summary /// 权限授权Handler /// /summary public class PermissionHandler : AuthorizationHandlerPermissionRequirement { /// summary /// 验证方案提供对象 /// /summary public IAuthenticationSchemeProvider Schemes { get; set; } /// summary /// 用户权限集合 /// /summary ListPermission _permissions; /// summary /// 构造 /// /summary /// param nameschemes/param public PermissionHandler(IAuthenticationSchemeProvider schemes, ListPermission permissionsnull) { Schemes schemes; _permissions permissions; } protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement) { //从AuthorizationHandlerContext转成HttpContext以便取出表求信息 var httpContext (context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext).HttpContext; //请求Url var questUrl httpContext.Request.Path.Value.ToLower(); //判断请求是否停止 var handlers httpContext.RequestServices.GetRequiredServiceIAuthenticationHandlerProvider(); foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync()) { var handler await handlers.GetHandlerAsync(httpContext, scheme.Name) as IAuthenticationRequestHandler; if (handler ! null await handler.HandleRequestAsync()) { context.Fail(); return; } } //判断请求是否拥有凭据即有没有登录 var defaultAuthenticate await Schemes.GetDefaultAuthenticateSchemeAsync(); if (defaultAuthenticate ! null) { var result await httpContext.AuthenticateAsync(defaultAuthenticate.Name); //result?.Principal不为空即登录成功 if (result?.Principal ! null) { httpContext.User result.Principal; //权限中是否存在请求的url if (_permissions!null_permissions.GroupBy(g g.Url).Where(w w.Key.ToLower() questUrl).Count() 0) { var name httpContext.User.Claims.SingleOrDefault(s s.Type requirement.ClaimType).Value; //验证权限 if (_permissions.Where(w w.Name name w.Url.ToLower() questUrl).Count() 0) { //无权限跳转到拒绝页面  httpContext.Response.Redirect(requirement.DeniedAction); context.Succeed(requirement); return; } } //判断过期时间 if (DateTime.Parse(httpContext.User.Claims.SingleOrDefault(s s.Type ClaimTypes.Expiration).Value) DateTime.Now) { context.Succeed(requirement); } else { context.Fail(); } return; } } //判断没有登录时是否访问登录的url,并且是Post请求并且是form表单提交类型否则为失败 if (!questUrl.Equals(requirement.LoginPath.ToLower(), StringComparison.Ordinal) (!httpContext.Request.Method.Equals(POST) || !httpContext.Request.HasFormContentType)) { context.Fail(); return; } context.Succeed(requirement); } } } JwtToken.cs using System; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; namespace Ocelot.JWTAuthorizePolicy { /// summary /// JWTToken生成类 /// /summary public class JwtToken { /// summary /// 获取基于JWT的Token /// /summary /// param nameusername/param /// returns/returns public static dynamic BuildJwtToken(Claim[] claims, PermissionRequirement permissionRequirement) { var now DateTime.UtcNow; var jwt new JwtSecurityToken( issuer: permissionRequirement.Issuer, audience: permissionRequirement.Audience, claims: claims, notBefore: now, expires: now.Add(permissionRequirement.Expiration), signingCredentials: permissionRequirement.SigningCredentials ); var encodedJwt new JwtSecurityTokenHandler().WriteToken(jwt); var responseJson new { Status true, access_token encodedJwt, expires_in permissionRequirement.Expiration.TotalMilliseconds, token_type Bearer }; return responseJson; } } } OcelotJwtBearerExtension.cs本类型中的方法分别用于网关web服务和验证服务请参看注释 using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.DependencyInjection; using Microsoft.IdentityModel.Tokens; using System; using System.Collections.Generic; using System.Security.Claims; using System.Text; namespace Ocelot.JWTAuthorizePolicy { /// summary /// Ocelot下JwtBearer扩展 /// /summary public static class OcelotJwtBearerExtension { /// summary /// 注入Ocelot下JwtBearer在ocelot网关的Startup的ConfigureServices中调用 /// /summary /// param nameservicesIServiceCollection/param /// param nameissuer发行人/param /// param nameaudience订阅人/param /// param namesecret密钥/param /// param namedefaultScheme默认架构/param /// param nameisHttps是否https/param /// returns/returns public static AuthenticationBuilder AddOcelotJwtBearer(this IServiceCollection services, string issuer, string audience, string secret, string defaultScheme, bool isHttps false) { var keyByteArray Encoding.ASCII.GetBytes(secret); var signingKey new SymmetricSecurityKey(keyByteArray); var tokenValidationParameters new TokenValidationParameters { ValidateIssuerSigningKey true, IssuerSigningKey signingKey, ValidateIssuer true, ValidIssuer issuer,//发行人 ValidateAudience true, ValidAudience audience,//订阅人 ValidateLifetime true, ClockSkew TimeSpan.Zero, RequireExpirationTime true, }; return services.AddAuthentication(options { options.DefaultScheme defaultScheme; }) .AddJwtBearer(defaultScheme, opt { //不使用https opt.RequireHttpsMetadata isHttps; opt.TokenValidationParameters tokenValidationParameters; }); } /// summary /// 注入Ocelot jwt策略在业务API应用中的Startup的ConfigureServices调用 /// /summary /// param nameservicesIServiceCollection/param /// param nameissuer发行人/param /// param nameaudience订阅人/param /// param namesecret密钥/param /// param namedefaultScheme默认架构/param /// param namepolicyName自定义策略名称/param /// param namedeniedUrl拒绝路由/param /// param nameisHttps是否https/param /// returns/returns public static AuthenticationBuilder AddOcelotPolicyJwtBearer(this IServiceCollection services, string issuer, string audience, string secret, string defaultScheme, string policyName, string deniedUrl, bool isHttps false) { var keyByteArray Encoding.ASCII.GetBytes(secret); var signingKey new SymmetricSecurityKey(keyByteArray); var tokenValidationParameters new TokenValidationParameters { ValidateIssuerSigningKey true, IssuerSigningKey signingKey, ValidateIssuer true, ValidIssuer issuer,//发行人 ValidateAudience true, ValidAudience audience,//订阅人 ValidateLifetime true, ClockSkew TimeSpan.Zero, RequireExpirationTime true, }; var signingCredentials new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256); //如果第三个参数是ClaimTypes.Role上面集合的每个元素的Name为角色名称如果ClaimTypes.Name即上面集合的每个元素的Name为用户名 var permissionRequirement new PermissionRequirement( deniedUrl, ClaimTypes.Role, issuer, audience, signingCredentials, expiration: TimeSpan.FromHours(10) ); //注入授权Handler services.AddSingletonIAuthorizationHandler, PermissionHandler(); services.AddSingleton(permissionRequirement); return services.AddAuthorization(options { options.AddPolicy(policyName, policy policy.Requirements.Add(permissionRequirement)); }) .AddAuthentication(options { options.DefaultScheme defaultScheme; }) .AddJwtBearer(defaultScheme, o { //不使用https o.RequireHttpsMetadata isHttps; o.TokenValidationParameters tokenValidationParameters; }); } /// summary /// 注入Token生成器参数在token生成项目的Startup的ConfigureServices中使用 /// /summary /// param nameservicesIServiceCollection/param /// param nameissuer发行人/param /// param nameaudience订阅人/param /// param namesecret密钥/param /// param namedeniedUrl拒绝路由/param /// returns/returns public static IServiceCollection AddJTokenBuild(this IServiceCollection services, string issuer, string audience, string secret, string deniedUrl) { var signingCredentials new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secret)), SecurityAlgorithms.HmacSha256); //如果第三个参数是ClaimTypes.Role上面集合的每个元素的Name为角色名称如果ClaimTypes.Name即上面集合的每个元素的Name为用户名 var permissionRequirement new PermissionRequirement( deniedUrl, ClaimTypes.Role, issuer, audience, signingCredentials, expiration: TimeSpan.FromHours(10) ); return services.AddSingleton(permissionRequirement); } } } 接下来看AuthenticationAPI项目 appsettings.json { Logging: { IncludeScopes: false, Debug: { LogLevel: { Default: Information } }, Console: { LogLevel: { Default: Information } } }, Audience: { Secret: ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890, Issuer: gsw, Audience: everone } } Startup.cs using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Ocelot.JWTAuthorizePolicy; namespace AuthenticationAPI { public class Startup { public Startup(IConfiguration configuration) { Configuration configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { var audienceConfig Configuration.GetSection(Audience); //注入OcelotJwtBearer services.AddJTokenBuild(audienceConfig[Issuer], audienceConfig[Issuer], audienceConfig[Secret], /api/denied); services.AddMvc(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseMvc(); } } } PermissionController.cs using System; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using System.Security.Claims; using Microsoft.AspNetCore.Authentication.JwtBearer; using Ocelot.JWTAuthorizePolicy; namespace AuthenticationAPI {  public class PermissionController : Controller { /// summary /// 自定义策略参数 /// /summary PermissionRequirement _requirement; public PermissionController(PermissionRequirement requirement) { _requirement requirement; } [AllowAnonymous] [HttpPost(/authapi/login)] public IActionResult Login(string username, string password) { var isValidated (username gsw password 111111)|| (username ggg password 222222); var roleusernamegsw?admin :system; if (!isValidated) { return new JsonResult(new { Status false, Message 认证失败 }); } else {  //如果是基于用户的授权策略这里要添加用户;如果是基于角色的授权策略这里要添加角色 var claims new Claim[] { new Claim(ClaimTypes.Name, username), new Claim(ClaimTypes.Role, role), new Claim(ClaimTypes.Expiration ,DateTime.Now.AddSeconds(_requirement.Expiration.TotalSeconds).ToString())}; //用户标识 var identity new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme); identity.AddClaims(claims); var token JwtToken.BuildJwtToken(claims, _requirement); return new JsonResult(token); } }  } } DemoAAPI项目DemoBAPI项目类似 appsettings.json与网关AuthenticationAPI相同 Startup.cs using System.Collections.Generic; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Ocelot.JWTAuthorizePolicy; namespace DemoAAPI { public class Startup { public Startup(IConfiguration configuration) { Configuration configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { //读取配置文件 var audienceConfig Configuration.GetSection(Audience); services.AddOcelotPolicyJwtBearer(audienceConfig[Issuer], audienceConfig[Issuer], audienceConfig[Secret], GSWBearer, Permission, /demoaapi/denied); //这个集合模拟用户权限表,可从数据库中查询出来 var permission new ListPermission { new Permission { Url/demoaapi/values, Namesystem}, new Permission { Url/, Namesystem}  }; services.AddSingleton(permission); services.AddMvc(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(Configuration.GetSection(Logging)); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseMvc(); } } } ValuesController.cs using System.Collections.Generic; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace DemoAAPI.Controllers { [Authorize(Permission)] [Route(demoaapi/[controller])] public class ValuesController : Controller {  [HttpGet] public IEnumerablestring Get() { return new string[] { DemoA服务, 请求 }; } [AllowAnonymous] [HttpGet(/demoaapi/denied)] public IActionResult Denied() { return new JsonResult(new { Status false, Message demoaapi你无权限访问 }); } } } OcelotGateway项目 configuration.json注意每个连接的AuthenticationOptions. AuthenticationProviderKey,要设置成 { ReRoutes: [ { DownstreamPathTemplate: /demoaapi/values, DownstreamScheme: http, DownstreamPort: 5001, DownstreamHost: localhost, UpstreamPathTemplate: /demoaapi/values, UpstreamHttpMethod: [ Get ], QoSOptions: { ExceptionsAllowedBeforeBreaking: 3, DurationOfBreak: 10, TimeoutValue: 5000 }, HttpHandlerOptions: { AllowAutoRedirect: false, UseCookieContainer: false }, AuthenticationOptions: { AuthenticationProviderKey: GSWBearer, AllowedScopes: [] } }, { DownstreamPathTemplate: /demoaapi/denied, DownstreamScheme: http, DownstreamPort: 5001, DownstreamHost: localhost, UpstreamPathTemplate: /demoaapi/denied, UpstreamHttpMethod: [ Get ], QoSOptions: { ExceptionsAllowedBeforeBreaking: 3, DurationOfBreak: 10, TimeoutValue: 5000 }, AuthenticationOptions: { } }, { DownstreamPathTemplate: /demobapi/values, DownstreamScheme: http, DownstreamPort: 5002, DownstreamHost: localhost, UpstreamPathTemplate: /demobapi/values, UpstreamHttpMethod: [ Get ], QoSOptions: { ExceptionsAllowedBeforeBreaking: 3, DurationOfBreak: 10, TimeoutValue: 5000 }, HttpHandlerOptions: { AllowAutoRedirect: false, UseCookieContainer: false }, AuthenticationOptions: { AuthenticationProviderKey: GSWBearer, AllowedScopes: [] } }, { DownstreamPathTemplate: /demobapi/denied, DownstreamScheme: http, DownstreamPort: 5002, DownstreamHost: localhost, UpstreamPathTemplate: /demobapi/denied, UpstreamHttpMethod: [ Get ], QoSOptions: { ExceptionsAllowedBeforeBreaking: 3, DurationOfBreak: 10, TimeoutValue: 5000 }, AuthenticationOptions: { } }, { DownstreamPathTemplate: /authapi/login, DownstreamScheme: http, DownstreamPort: 5003, DownstreamHost: localhost, UpstreamPathTemplate: /authapi/login, UpstreamHttpMethod: [ Get, Post ], QoSOptions: { ExceptionsAllowedBeforeBreaking: 3, DurationOfBreak: 10, TimeoutValue: 5000 }, AuthenticationOptions: { } } ] } Startup.cs using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Ocelot.DependencyInjection; using Ocelot.Middleware; using Ocelot.JWTAuthorizePolicy; namespace OcelotGateway { public class Startup { public Startup(IConfiguration configuration) { Configuration configuration; } public IConfiguration Configuration { get; }  public void ConfigureServices(IServiceCollection services) { var audienceConfig Configuration.GetSection(Audience); //注入OcelotJwtBearer services.AddOcelotJwtBearer(audienceConfig[Issuer], audienceConfig[Issuer], audienceConfig[Secret], GSWBearer); //注入配置文件AddOcelot要求参数是IConfigurationRoot类型所以要作个转换 services.AddOcelot(Configuration as ConfigurationRoot); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseOcelot().Wait(); } } } 接下来是测试项目创建一个控制项目TestClient Nuget中添加RestSharp包 Program.cs using RestSharp; using System; using System.Diagnostics; namespace TestClient { class Program { /// summary /// 访问Url /// /summary static string _url http://127.0.0.1:5000; static void Main(string[] args) { Console.Title TestClient; dynamic token null; while (true) { Console.WriteLine(1、登录【admin】 2、登录【system】 3、登录【错误用户名密码】 4、查询HisUser数据 5、查询LisUser数据 ); var mark Console.ReadLine(); var stopwatch new Stopwatch(); stopwatch.Start(); switch (mark) { case 1: token AdminLogin(); break; case 2: token SystemLogin(); break; case 3: token NullLogin(); break; case 4: DemoAAPI(token); break; case 5: DemoBAPI(token); break; } stopwatch.Stop(); TimeSpan timespan stopwatch.Elapsed; Console.WriteLine($间隔时间{timespan.TotalSeconds}); tokenString Bearer Convert.ToString(token?.access_token); } } static string tokenString ; static dynamic NullLogin() { var loginClient new RestClient(_url); var loginRequest new RestRequest(/authapi/login, Method.POST); loginRequest.AddParameter(username, gswaa); loginRequest.AddParameter(password, 111111); //或用用户名密码查询对应角色 loginRequest.AddParameter(role, system); IRestResponse loginResponse loginClient.Execute(loginRequest); var loginContent loginResponse.Content; Console.WriteLine(loginContent); return Newtonsoft.Json.JsonConvert.DeserializeObject(loginContent); } static dynamic SystemLogin() { var loginClient new RestClient(_url); var loginRequest new RestRequest(/authapi/login, Method.POST); loginRequest.AddParameter(username, ggg); loginRequest.AddParameter(password, 222222); IRestResponse loginResponse loginClient.Execute(loginRequest); var loginContent loginResponse.Content; Console.WriteLine(loginContent); return Newtonsoft.Json.JsonConvert.DeserializeObject(loginContent); } static dynamic AdminLogin() { var loginClient new RestClient(_url); var loginRequest new RestRequest(/authapi/login, Method.POST); loginRequest.AddParameter(username, gsw); loginRequest.AddParameter(password, 111111); IRestResponse loginResponse loginClient.Execute(loginRequest); var loginContent loginResponse.Content; Console.WriteLine(loginContent); return Newtonsoft.Json.JsonConvert.DeserializeObject(loginContent); } static void DemoAAPI(dynamic token) { var client new RestClient(_url); //这里要在获取的令牌字符串前加Bearer string tk Bearer Convert.ToString(token?.access_token); client.AddDefaultHeader(Authorization, tk); var request new RestRequest(/demoaapi/values, Method.GET); IRestResponse response client.Execute(request); var content response.Content; Console.WriteLine($状态码{(int)response.StatusCode} 状态信息{response.StatusCode} 返回结果{content}); } static void DemoBAPI(dynamic token) { var client new RestClient(_url); //这里要在获取的令牌字符串前加Bearer string tk Bearer Convert.ToString(token?.access_token); client.AddDefaultHeader(Authorization, tk); var request new RestRequest(/demobapi/values, Method.GET); IRestResponse response client.Execute(request); var content response.Content; Console.WriteLine($状态码{(int)response.StatusCode} 状态信息{response.StatusCode} 返回结果{content}); } } } 相关文章 Ocelot——初识基于.Net Core的API网关 Ocelot API网关的实现剖析 微服务网关Ocelot API网关Ocelot 使用Polly 处理部分失败问题 谈谈微服务中的 API 网关API Gateway Ocelot网关 原文http://www.cnblogs.com/axzxs2001/p/8005084.html .NET社区新闻深度好文欢迎访问公众号文章汇总 http://www.csharpkit.com
http://www.pierceye.com/news/971520/

相关文章:

  • 电商网站怎么做的公司网站被黑有不良信息 做笔录
  • 前端开发可以做网站运营吗规模大的企业建站
  • 手表网网站模仿网站建设
  • 有做的小说网站怎样建设网站后台
  • 珠海高端网站制作公司兰州市建设局官方网站
  • 网站如何改首页模块有了主机如何做网站
  • 郑州哪有做网站的前端学习网站
  • 电商网站建设概念wordpress主题个人博客
  • 福州网站建设多少钱全网商城系统
  • 自己如何做团购网站在设计赚钱的网站
  • 支持wap网站的系统百度seo关键词排名查询
  • 做最好最全的命理网站郴州网络营销
  • wap网站技术怎么查询网站的建站时间
  • 深圳网站开发专业团队2o18江苏建设网站施工员模试卷
  • 网站购物建设实训心得体会中山皇冠建设开发有限公司网站
  • 做360pc网站排名首页学校网站建设工作计划
  • 网站设计与制作的基本步骤移动互联网论文
  • 建设部网站2015年第158号中国建筑材料网官网
  • 大理网站建设沛宣郑州模板建站代理
  • 新浪博客怎么上传wordpress佛山推广seo排名
  • 北京建设网站有哪些公司网络营销方法有哪几种
  • 在中国备案的网站服务器利用小说网站做本站优化
  • 网站风格的表现形式重庆观音桥房价
  • 哪些公司的网站做的很好手机网页素材
  • 天津地铁建设网站百度广告太多
  • 保定php网站制作wordpress的seo收件箱
  • 网站建设公司-跨界鱼科技优外国网站设计风格
  • 网站营销平台注册微信公众号流程
  • 西安专业网站建设服务公司商标查询网入口
  • 营销型网站设计房地产wordpress多媒体路径