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

个人网站设计内容和要求泗水网站建设

个人网站设计内容和要求,泗水网站建设,wordpress众筹,wordpress xiu5.3“我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕#xff1f; 尝试使用Okta API进行托管身份验证#xff0c;授权和多因素身份验证。 每个开发人员都希望能够更快#xff0c;更有效地进行构建以支持规模。 使用Spring构… “我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕 尝试使用Okta API进行托管身份验证授权和多因素身份验证。 每个开发人员都希望能够更快更有效地进行构建以支持规模。 使用Spring构建微服务架构可以为您的架构增加弹性和弹性这将使其优雅地失效并无限扩展。 借助Spring Security及其OAuth 2.0支持您还可以获得锁定API网关以及后端服务器所需的一切。 您可以将其设置为自动将访问令牌从一个应用程序传播到另一个应用程序以确保在此过程中所有内容保持安全和加密。 本教程向您展示如何将Spring Security与OAuth 2.0和Okta结合使用来锁定您的微服务架构。 带有Spring Boot Spring Cloud的微服务架构 本教程将向您展示如何为我之前写的教程“ 使用Spring Boot为Microbrews构建微服务体系结构”增加安全性。 带有Spring Boot和Spring Cloud的基本微服务架构如下图所示。 完成本教程后您将获得Spring Security锁定的一切Okta将为OAuth提供授权。 您的边缘服务也称为API网关将具有一个Feign客户端和一个处理正常故障转移的Hystrix该客户端将随您的访问令牌一起传递。 首先您需要克隆上述文章的已完成项目。 git clone https://github.com/oktadeveloper/spring-boot-microservices-example.git在Okta中创建Web应用程序 如果您还没有请创建一个永久免费的Okta Developer帐户 。 完成设置过程后登录到您的帐户并导航至Applications Add Application 。 单击Web 然后单击下一步 。 在下一页上输入以下值然后单击完成 。 应用名称 Spring OAuth 基本URI http://localhost:8081 登录重定向URI http://localhost:8081/login 记下clientId和client机密值因为它们将用于配置Spring Boot应用程序。 您需要在ID令牌中添加一个roles声明以便将Okta中的组转换为Spring Security机构。 在Okta开发人员控制台中导航到API 授权服务器 单击授权服务器选项卡并编辑默认选项卡。 点击索赔标签然后添加索赔 。 将其命名为“角色”并将其包含在ID令牌中。 将值类型设置为“ Groups”并将过滤器设置为.*的正则表达式。 将Spring Security OAuth添加到边缘服务应用程序 边缘服务应用程序处理与beer-catalog-service的通信因此它是开始集成OAuth的最佳位置。 在edge-service/pom.xml 添加Spring Security的依赖关系其OAuth支持和JWT支持。 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-security/artifactId /dependency dependencygroupIdorg.springframework.security.oauth.boot/groupIdartifactIdspring-security-oauth2-autoconfigure/artifactIdversion2.0.1.RELEASE/version /dependency 将以下Zuul路由添加到edge-service/src/main/resources/application.properties 。 zuul.routes.beer-catalog-service.path/beers zuul.routes.beer-catalog-service.urlhttp://localhost:8080zuul.routes.home.path/home zuul.routes.home.urlhttp://localhost:8080 打开edge-service/src/main/java/com/example/edgeservice/EdgeServiceApplication.java并添加EnableOAuth2Sso以启用OAuth身份验证。 import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso; ... EnableOAuth2Sso SpringBootApplication public class EdgeServiceApplication { 添加EnableOAuth2Sso导致Spring Security查找大量属性。 将以下属性添加到edge-service/src/main/resources/application.properties 。 security.oauth2.client.client-id{yourClientId} security.oauth2.client.client-secret{yourClientSecret} security.oauth2.client.access-token-urihttps://{yourOktaDomain}.com/oauth2/default/v1/token security.oauth2.client.user-authorization-urihttps://{yourOktaDomain}.com/oauth2/default/v1/authorize security.oauth2.client.scopeopenid profile email security.oauth2.resource.user-info-urihttps://{yourOktaDomain}.com/oauth2/default/v1/userinfo security.oauth2.resource.token-info-urihttps://{yourOktaDomain}.com/oauth2/default/v1/introspect security.oauth2.resource.prefer-token-infofalse 提示如果在上面的代码片段中看到{yourOktaDomain} 请登录到Okta帐户并刷新此页面。 它将用您的域替换该值。 将ResourceServerConfig.java类添加到与EdgeServiceApplication相同的包中。 package com.example.edgeservice;import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;Configuration EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter {Overridepublic void configure(HttpSecurity http) throws Exception {http.requestMatcher(new RequestHeaderRequestMatcher(Authorization)).authorizeRequests().antMatchers(/**).authenticated();} } 至此您已经完成了足以登录到Edge Service应用程序的配置但是它无法与下游beer-catalog-service进行通信。 将Spring Security OAuth添加到Beer Catalog Service 在beer-catalog-service/pom.xml 添加与添加到Edge Service相同的依赖项以及Thymeleaf的依赖项。 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-security/artifactId /dependency dependencygroupIdorg.springframework.security.oauth.boot/groupIdartifactIdspring-security-oauth2-autoconfigure/artifactIdversion2.0.1.RELEASE/version /dependency dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-thymeleaf/artifactId /dependency 将相同的属性添加到beer-catalog-service/src/main/resources/application.properties 。 security.oauth2.client.client-id{yourClientId} security.oauth2.client.client-secret{yourClientSecret} security.oauth2.client.access-token-urihttps://{yourOktaDomain}.com/oauth2/default/v1/token security.oauth2.client.user-authorization-urihttps://{yourOktaDomain}.com/oauth2/default/v1/authorize security.oauth2.client.scopeopenid profile email security.oauth2.resource.user-info-urihttps://{yourOktaDomain}.com/oauth2/default/v1/userinfo security.oauth2.resource.token-info-urihttps://{yourOktaDomain}.com/oauth2/default/v1/introspect security.oauth2.resource.prefer-token-infofalse 提示添加这些属性的替代方法是使用环境变量。 例如 SECURITY_OAUTH2_CLIENT_CLIENT_ID将是用于指定security.oauth2.client.client-id的环境变量。 使用环境变量将允许您从一个位置更改两个应用程序的设置。 在beer-catalog-service/src/main/java/com/example/beercatalogservice/HomeController.java创建一个HomeController来呈现用户信息以便您可以验证身份验证是否正常。 package com.example.beercatalogservice;import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping;import java.security.Principal; import java.util.Map;Controller public class HomeController {GetMapping(/home)SuppressWarnings(unchecked)public String howdy(Model model, Principal principal) {OAuth2Authentication authentication (OAuth2Authentication) principal;MapString, Object user (MapString, Object) authentication.getUserAuthentication().getDetails();model.addAttribute(user, user);return home;} } 在beer-catalog-service/src/main/resources/templates/home.html创建一个home.html模板并使用以下代码填充它。 !DOCTYPE HTML html xmlns:thhttp://www.thymeleaf.org headstyleth {text-align: left;}td {white-space: nowrap;}td:first-child {font-family: Courier, monospace;font-size: 0.9em;color: #343434;}/style /head body h1Hellospan th:if${user} th:text ${user.name} Joe/span!/h1 div th:unless${user}a th:href{/login}Login/a /div div th:if${user}form idlogoutForm th:action{/logout} methodpostinput typesubmit valueLogout//form /divh2User Properties/h2 tabletheadtrthName/ththValue/th/tr/theadtbodytrtdsub/tdtd th:text${user.sub}/td/trtrtdname/tdtd th:text${user.name}/td/trtrtdgiven_name/tdtd th:text${user.given_name}/td/trtrtdfamily_name/tdtd th:text${user.family_name}/td/trtrtdpreferred_username/tdtd th:text${user.preferred_username}/td/trtrtdemail/tdtd th:text${user.email}/td/trtrtdroles/tdtd th:text${user.roles}/td/tr/tbody /table /body /html 在与HomeController相同的包中创建ResourceServerConfig.java类。 此类配置Spring Security因此可以保护所有端点但那些通过Authorization标头访问的端点除外。 package com.example.beercatalogservice;import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;Configuration EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter {Overridepublic void configure(HttpSecurity http) throws Exception {http.requestMatcher(new RequestHeaderRequestMatcher(Authorization)).authorizeRequests().anyRequest().fullyAuthenticated();} }添加伪装的RequestInterceptor 用于与beer-catalog-service对话的FeignClient Authorization标头。 为了使其UserFeignClientInterceptor 请在与EdgeServiceApplication相同的目录中创建UserFeignClientInterceptor类。 package com.example.edgeservice;import feign.RequestInterceptor; import feign.RequestTemplate; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails; import org.springframework.stereotype.Component;Component public class UserFeignClientInterceptor implements RequestInterceptor {private static final String AUTHORIZATION_HEADER Authorization;private static final String BEARER_TOKEN_TYPE Bearer;Overridepublic void apply(RequestTemplate template) {SecurityContext securityContext SecurityContextHolder.getContext();Authentication authentication securityContext.getAuthentication();if (authentication ! null authentication.getDetails() instanceof OAuth2AuthenticationDetails) {OAuth2AuthenticationDetails details (OAuth2AuthenticationDetails) authentication.getDetails();template.header(AUTHORIZATION_HEADER, String.format(%s %s, BEARER_TOKEN_TYPE, details.getTokenValue()));}} } 注册为Bean里面EdgeServiceApplication类。 import feign.RequestInterceptor; ... public class EdgeServiceApplication {public static void main(String[] args) {SpringApplication.run(EdgeServiceApplication.class, args);}Beanpublic RequestInterceptor getUserFeignClientInterceptor() {return new UserFeignClientInterceptor();} } 为了使Hystrix了解安全上下文您需要在edge-service/src/main/resources/application.properties 添加两个属性 feign.hystrix.enabledtrue hystrix.shareSecurityContexttrue验证安全通信 您可以通过启动所有Spring Boot应用程序来验证edge-service和beer-catalog-service之间的通信。 首先启动eureka-service cd eureka-service ./mvnw spring-boot:run 在新的终端窗口中启动beer-catalog-service cd beer-catalog-service ./mvnw spring-boot:run 在另一个终端窗口中启动edge-service cd edge-service ./mvnw spring-boot:run 打开浏览器并导航到http://localhost:8081/good-beers 。 您应该被重定向到Okta域并看到一个登录页面提示您输入凭据。 输入您用来创建帐户的凭据结果将看到一列优质啤酒。 如果您尝试导航到http://localhost:8081/home 它将无法正常工作。 这是因为您需要将Spring Cloud Security添加到edge-service/pom.xml以中继Zuul代理的访问令牌。 dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-security/artifactId /dependency 没有这种依赖性对/good-beers请求将可以工作因为已配置Feign但对/home请求将不会因为Zuul需要Spring Cloud Security。 重新启动边缘服务器应用程序导航到http://localhost:8081/home 您将在下一页看到您的用户详细信息。 在Spring Boot 2.0中保护下游服务 使用Spring Boot 1.5.x将Actuator作为依赖项包括在内将触发Actuator Security并使其受到保护从而保护了http://localhost:8080 。 在Spring Boot 2.x中拥有WebSecurityConfigurerAdapter会导致执行器安全性降低。 在Beer Catalog Service应用程序中 ResourceServerConfig导致此行为。 要确保执行器端点安全并使其无法直接访问http://localhost:8080 请在beer-catalog-service/src/main/resources/application.properties添加要公开的端点 management.endpoints.web.exposure.includebeans,mappings 然后创建一个SecurityConfig类与ResourceServerConfig放在同一包中。 package com.example.beercatalogservice;import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter {Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).hasRole(ADMIN).anyRequest().authenticated().and().httpBasic();} } 进行这些更改后重新启动beer-catalog-service并见证其保护。 注意由于出现403错误我无法使注销按钮正常工作。 我尝试在边缘服务应用程序csrf().requireCsrfProtectionMatcher(r - false)到ResourceServerConfig 但这没有帮助。 我给Spring Security团队发送了一封电子邮件询问他们是否有任何建议。 将Okta的登录小部件添加到Angular客户端 要使用Okta的登录小部件您需要在Okta中修改您的应用以启用“ 隐式”授予类型。 登录到您的帐户导航至“ 应用程序” “ Spring OAuth” “ 常规”选项卡然后单击“ 编辑” 。 在“ 允许的授予类型”下启用“ 隐式混合” 并选中其下方的两个复选框。 在登录重定向URI下添加http://localhost:4200 然后点击保存 。 为了使“登录小部件”向该应用程序发出请求您还需要将客户端URL配置为可信来源。 单击API 可信 来源 添加来源 。 输入http://localhost:4200作为原始URL并选中其下方的两个复选框。 打开一个终端导航到spring-boot-microservices-example/client 然后使用npm安装客户端的依赖项。 cd client npm install 安装Okta的登录小部件 使其可以与受保护的服务器进行通信。 npm install okta/okta-signin-widget --save 将小部件CSS添加到client/src/styles.css import ~okta/okta-signin-widget/dist/css/okta-sign-in.min.css; import ~okta/okta-signin-widget/dist/css/okta-theme.css; 创建client/src/app/shared/okta/okta.service.ts并使用它来配置小部件以与您的Okta租户对话。 请确保在下面的代码中替换{yourOktaDomain}和{clientId} 。 import { Injectable } from angular/core; import * as OktaSignIn from okta/okta-signin-widget;Injectable() export class OktaService {widget;constructor() {this.widget new OktaSignIn({baseUrl: https://{yourOktaDomain}.com,clientId: {yourClientId},authParams: {issuer: default,responseType: [id_token, token],scopes: [openid, email, profile]}});}getWidget() {return this.widget;}getIdToken() {return this.widget.tokenManager.get(idToken);}getAccessToken() {return this.widget.tokenManager.get(accessToken);} } 将OktaService作为提供程序添加到client/src/app/app.module.ts 。 import { OktaService } from ./shared/okta/okta.service;NgModule({...providers: [OktaService],bootstrap: [AppComponent] }) export class AppModule { } 修改client/src/app/shared/beer/beer.service.ts以读取访问令牌并将其设置在Authorization标头中如果存在。 import { Injectable } from angular/core; import { HttpClient, HttpHeaders } from angular/common/http; import { Observable } from rxjs/Observable; import { OktaService } from ../okta/okta.service;Injectable() export class BeerService {constructor(private http: HttpClient, private oktaService: OktaService) {}getAll(): Observable {let headers: HttpHeaders new HttpHeaders();if (this.oktaService.getAccessToken()) {const accessToken this.oktaService.getAccessToken();// headers is immutable, so re-assignheaders headers.append(Authorization, accessToken.tokenType accessToken.accessToken);}return this.http.get(http://localhost:8081/good-beers, {headers: headers});} } 修改app.component.html 为小部件添加一个占位符并显示一个部分以显示用户名和注销按钮。 mat-toolbar colorprimaryspanWelcome to {{title}}!/span /mat-toolbar!-- Container to inject the Sign-In Widget -- div idokta-signin-container/divdiv *ngIfuserh2Welcome {{user?.name}}!/h2button mat-raised-button (click)logout()Logout/buttonapp-beer-list/app-beer-list /div 您会注意到HTML中的user变量。 要解决此问题您需要更改client/src/app/app.component.ts以使其呈现登录小部件。 Angular的ChangeDetectorRef用于在事物发生更改并且渲染需要处理更新的变量时通知Angular。 import { ChangeDetectorRef, Component, OnInit } from angular/core; import { OktaService } from ./shared/okta/okta.service;Component({selector: app-root,templateUrl: ./app.component.html,styleUrls: [./app.component.css] }) export class AppComponent implements OnInit {title app;user;signIn;constructor(private oktaService: OktaService, private changeDetectorRef: ChangeDetectorRef) {this.signIn oktaService.getWidget();}showLogin() {this.signIn.renderEl({el: #okta-signin-container}, (response) {if (response.status SUCCESS) {response.forEach(token {if (token.idToken) {this.signIn.tokenManager.add(idToken, token);this.user this.getUser(token);}if (token.accessToken) {this.signIn.tokenManager.add(accessToken, token);}});this.signIn.remove();this.changeDetectorRef.detectChanges();}});}getUser(token) {return {name: token.claims.name,email: token.claims.email,username: token.claims.preferred_username};}ngOnInit() {this.signIn.session.get((response) {if (response.status ! INACTIVE) {const token this.oktaService.getIdToken();this.user this.getUser(token);this.changeDetectorRef.detectChanges();} else {this.showLogin();}});}logout() {this.signIn.signOut(() {this.user undefined;this.changeDetectorRef.detectChanges();this.showLogin();});} } 为了使BeerListComponent 在src/app/beer-list/beer-list.component.ts 来检测你已经登录您需要使用添加在构造函数依赖ChangeDetectorRef并调用它的detectChanges()方法时您可以在每种beer上设置giphyUrl属性。 import { ChangeDetectorRef, Component, OnInit } from angular/core; import { BeerService, GiphyService } from ../shared;Component({selector: app-beer-list,templateUrl: ./beer-list.component.html,styleUrls: [./beer-list.component.css],providers: [BeerService, GiphyService] }) export class BeerListComponent implements OnInit {beers: Arrayany;constructor(private beerService: BeerService, private giphyService: GiphyService,private changeDetectorRef: ChangeDetectorRef) { }ngOnInit() {this.beerService.getAll().subscribe(data {this.beers data;for (const beer of this.beers) {this.giphyService.get(beer.name).subscribe(url {beer.giphyUrl url;this.changeDetectorRef.detectChanges();});}},error console.log(error))} }验证身份验证作品 通过打开终端导航到client目录然后运行npm start client 。 将浏览器打开到http://localhost:4200 您应该看到类似以下的登录表单。 如果要调整表单的样式以免它与顶部工具栏不对请在styles.css添加以下内容。 #okta-signin-container {margin-top: 25px; } 您应该能够登录看到欢迎消息以及注销按钮。 但是由于控制台中出现以下错误您不会看到啤酒清单。 Failed to load http://localhost:8081/good-beers: Response for preflight is invalid (redirect) 发生这种情况是因为Spring Security无法识别/good-beers端点上的CrossOrigin批注。 要解决此问题请向EdgeServiceApplication添加一个simpleCorsFilter 。 import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.core.Ordered; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter;import java.util.Collections; ... public class EdgeServiceApplication {public static void main(String[] args) {SpringApplication.run(EdgeServiceApplication.class, args);}Beanpublic RequestInterceptor getUserFeignClientInterceptor() {return new UserFeignClientInterceptor();}Beanpublic FilterRegistrationBean simpleCorsFilter() {UrlBasedCorsConfigurationSource source new UrlBasedCorsConfigurationSource();CorsConfiguration config new CorsConfiguration();config.setAllowCredentials(true);config.setAllowedOrigins(Collections.singletonList(*));config.setAllowedMethods(Collections.singletonList(*));config.setAllowedHeaders(Collections.singletonList(*));source.registerCorsConfiguration(/**, config);FilterRegistrationBean bean new FilterRegistrationBean(new CorsFilter(source));bean.setOrder(Ordered.HIGHEST_PRECEDENCE);return bean;} } 重新启动边缘服务应用程序然后重试。 这次您应该取得巨大的成功 注意如果在生产中使用此配置则应将允许的来源从*更改为客户的URL。 部署到Cloud Foundry 要使用Pivotal Web Services在Cloud Foundry上部署所有内容您需要创建一个帐户下载/安装Cloud Foundry CLI并登录使用cf login -a api.run.pivotal.io 。 部署所有服务和Angular客户端要进行生产涉及很多步骤。 因此我编写了一个deploy.sh脚本来自动执行所有操作。 注意该脚本完成后您必须将客户端的URL作为登录重定向URI添加到Okta应用中。 您还需要在API Trusted Origins下将其添加为源 。 提示如果收到错误消息说明您使用的内存过多则可能必须升级Cloud Foundry订阅。 进一步了解Spring BootOAuth 2.0和微服务 本文向您展示了如何使用Spring SecurityOAuth和Okta保护微服务架构。 借助ZuulFeign和Spring Cloud Security您可以确保后端服务安全地通信。 本教程的源代码位于GitHub的“ oauth”分支中 。 git clone https://github.com/oktadeveloper/spring-boot-microservices-example.git git checkout oauth 本教程向您展示了如何在上一教程“ 使用Spring Boot为Microbrews构建微服务架构 ”中增加安全性。 如果您有兴趣了解Spring Security和OAuth 2.0的未来请参阅我们的Spring Security团队的好朋友Joe Grandja提供的有关Spring Security的下一代OAuth 2.0支持 。 此外JHipster对其OAuth支持使用相同的设置。 如果您对将Okta与JHipster结合使用感兴趣建议您阅读以下博客文章 使用OAuth 2.0和JHipster开发微服务架构 使用Ionic for JHipster创建具有OIDC身份验证的移动应用程序 在developer.okta.com/product上了解有关Okta及其API的更多信息。 如果您对本教程有疑问请在下面发表评论或在Twitter mraible上打我。 变更日志 2018年5月11日更新为使用Spring Boot 2.0和Okta登录小部件2.0.8。 请参阅spring-boot-microservices-example17中的示例应用程序更改 可以在okta.github.io2049中查看对此帖子的更改。 “我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕 尝试使用Okta API进行托管身份验证授权和多因素身份验证。 使用Spring Security和OAuth 2.0保护Spring微服务体系结构最初于2018年2月13日发布在Okta开发者博客上。 翻译自: https://www.javacodegeeks.com/2018/05/secure-a-spring-microservices-architecture-with-spring-security-and-oauth-2-0.html
http://www.zqtcl.cn/news/814151/

相关文章:

  • 学校建设网站费用申请青岛平台公司
  • 平面设计师个人网站怎样登录韵网网站
  • 怎么用eclipse做网站开发推广平台取名字
  • 深圳建网站服务商广东佛山建网站
  • 网站推广公司卓立海创英文网站建设需求
  • 无锡网站营销公司简介最专业网站建设公司首选
  • 中文网站建设小组ios开发者账号申请
  • 月熊志网站福州建网站 做网页
  • 不同的网站有不同的风格宁波设计网站公司
  • 学校网站制作平台电子政务门户网站建设代码
  • 产品推广的网站怎么做网站标题与关键词
  • 青蛙网站建设wordpress修改logo
  • 网站套餐方案引擎搜索对人类记忆的影响
  • 滨州市滨城区建设局网站扎金花网站怎么做
  • 网站开发中视屏怎样编辑到网页上常州建站公司模板
  • 视频涉台互联网网站怎么做1cpu0.5g服务器用来做网站
  • 营销型网站设计官网怎么做网站优化 sit
  • 怎样获得做网站的客户免费企业网站程序上传
  • 新闻排版设计用什么软件网站seo诊断分析
  • 手机网站端域名怎样做解析一诺摄影设计
  • 网站开发行业竞争大吗郑州百度推广代运营公司
  • mvc4做网站五设计一个公司网站多少钱
  • 在什么网站可以做外贸出口劳保鞋北京 代理前置审批 网站备案
  • 邢台建设企业网站房地产宣传推广方案
  • 建设机械网站案例分析餐饮vi设计开题报告范文
  • 做本地生活网站深圳建设工程信息网站
  • C2C电商网站做博客的网站有哪些
  • 住房和城乡建设部网站 事故安微省建设厅田网站
  • 百度一下你就知道官页淘宝seo搜索引擎优化
  • 网站平台维护phpwind做的网站