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

网站建设 课程 说明河北建设工程信息网停用公告

网站建设 课程 说明,河北建设工程信息网停用公告,pda智能巡检系统,数据开发网站模板Sa-Token 集成SpringBoot简要步骤 1.1 简单介绍 Sa-Token是一个轻量级Java权限认证框架。 主要解决的问题如下#xff1a; 登录认证 权限认证 单点登录 OAuth2.0 分布式Session会话 微服务网关鉴权等一系列权限相关问题。 1.2 登录认证 设计思路 对于一些登录之后…Sa-Token 集成SpringBoot简要步骤 1.1 简单介绍 Sa-Token是一个轻量级Java权限认证框架。 主要解决的问题如下 登录认证 权限认证 单点登录 OAuth2.0 分布式Session会话 微服务网关鉴权等一系列权限相关问题。 1.2 登录认证 设计思路 对于一些登录之后才能访问的接口例如查询我的账号资料我们通常的做法是增加一层接口校验 如果校验通过则正常返回数据。 如果校验未通过则抛出异常告知其需要先进行登录。 那么判断会话是否登录的依据是什么我们先来简单分析一下登录访问流程 用户提交name password参数调用登录接口。 登录成功返回这个用户的Token会话凭证。 用户后续的每次请求都携带上这个Token。 服务器根据Token判断此会话是否登录成功。 所谓登录认证指的就是服务器校验账号密码为用户颁发Token会话凭证的过程这个Token也是我们后续通过接口校验的关键所在。 登录与注销 根据以上思路我们需要一个会话登录的函数 // 会话登录参数填写要登录的账号id建议的数据类型long | int | String 不可以传入复杂类型如User、Admin 等等 StpUtil.login(Object id); 只此一句代码便可以使会话登录成功实际上Sa-Token在背后做了大量的工作包括但不限于 检查此账号是否已被封禁 检查此账号是否之前已有登录 为账号生成 Token 凭证与 Session 会话 通知全局侦听器xx 账号登录成功 将 Token 注入到请求上下文 等等其它工作…… 你暂时不需要完整的了解整个登录过程你只需要记住关键一点Sa-Token 为这个账号创建了一个Token凭证且通过Cookie 上下文返回给了前端。 所以一般情况下我们的登录接口代码会大致类似如下 // 会话登录接口 RequestMapping(doLogin) public SaResult doLogin(String name, String pwd) {// 第一步比对前端提交的账号名称、密码if(zhang.equals(name) 123456.equals(pwd)) {// 第二步根据账号id进行登录 StpUtil.login(10001);return SaResult.ok(登录成功);}return SaResult.error(登录失败); } 如果你对以上代码阅读没有压力你可能会注意到略显奇怪的一点此处仅仅做了会话登录但并没有主动向前端返回Token信息。是因为不需要吗严格来讲是需要的只不过StpUtil.login(id)方法利用了Cookie自动注入的特性省略了你手写返回Token的代码。 你需要了解Cookie最基本的两点 Cookie可以从后端控制往浏览器中写入Token值。 Cookie会在每次请求时自动提交Token值。 因此在Cookie功能的加持下我们可以仅靠StpUtil.login(id) 一句代码就完成登录认证。 除了登录方法我们还需要 // 当前会话注销登录 StpUtil.logout();// 获取当前会话是否已经登录返回true已登录false未登录 StpUtil.isLogin();// 检验当前会话是否已经登录, 如果未登录则抛出异常NotLoginException StpUtil.checkLogin(); 异常NotLoginException代表当前会话暂未登录可能的原因有很多 前端没有提交 Token 前端提交的 Token 是无效的 前端提交的 Token 已经过期 …… 等等 会话查询 // 获取当前会话账号id, 如果未登录则抛出异常NotLoginException StpUtil.getLoginId();// 类似查询API还有 StpUtil.getLoginIdAsString(); // 获取当前会话账号id, 并转化为String类型 StpUtil.getLoginIdAsInt(); // 获取当前会话账号id, 并转化为int类型 StpUtil.getLoginIdAsLong(); // 获取当前会话账号id, 并转化为long类型// ---------- 指定未登录情形下返回的默认值 ----------// 获取当前会话账号id, 如果未登录则返回null StpUtil.getLoginIdDefaultNull();// 获取当前会话账号id, 如果未登录则返回默认值 defaultValue可以为任意类型 StpUtil.getLoginId(T defaultValue); Token查询  // 获取当前会话的token值 StpUtil.getTokenValue();// 获取当前StpLogic的token名称 StpUtil.getTokenName();// 获取指定token对应的账号id如果未登录则返回 null StpUtil.getLoginIdByToken(String tokenValue);// 获取当前会话剩余有效期单位s返回-1代表永久有效 StpUtil.getTokenTimeout();// 获取当前会话的token信息参数 StpUtil.getTokenInfo(); 有关TokenInfo参数详解如下代码所示 {code: 200,msg: ok,data: {tokenName: satoken, // token名称tokenValue: e67b99f1-3d7a-4a8d-bb2f-e888a0805633, // token值isLogin: true, // 此token是否已经登录loginId: 10001, // 此token对应的LoginId未登录时为nullloginType: login, // 账号类型标识tokenTimeout: 2591977, // token剩余有效期 (单位: 秒)sessionTimeout: 2591977, // User-Session剩余有效时间 (单位: 秒)tokenSessionTimeout: -2, // Token-Session剩余有效时间 (单位: 秒)tokenActivityTimeout: -1, // token剩余无操作有效时间 (单位: 秒)loginDevice: default-device // 登录设备类型 }, } 小测试加深理解 新建LoginController复制以下代码 /*** 登录测试 */ RestController RequestMapping(/acc/) public class LoginController {// 测试登录 ---- http://localhost:8081/acc/doLogin?namezhangpwd123456RequestMapping(doLogin)public SaResult doLogin(String name, String pwd) {// 此处仅作模拟示例真实项目需要从数据库中查询数据进行比对 if(zhang.equals(name) 123456.equals(pwd)) {StpUtil.login(10001);return SaResult.ok(登录成功);}return SaResult.error(登录失败);}// 查询登录状态 ---- http://localhost:8081/acc/isLoginRequestMapping(isLogin)public SaResult isLogin() {return SaResult.ok(是否登录 StpUtil.isLogin());}// 查询 Token 信息 ---- http://localhost:8081/acc/tokenInfoRequestMapping(tokenInfo)public SaResult tokenInfo() {return SaResult.data(StpUtil.getTokenInfo());}// 测试注销 ---- http://localhost:8081/acc/logoutRequestMapping(logout)public SaResult logout() {StpUtil.logout();return SaResult.ok();}} 1.3 权限认证 设计思路 所谓权限认证核心逻辑就是判断一个账号是否拥有指定权限 有就让你通过。 没有那么禁止访问 深入到底层数据中就是每个账号都会拥有一个权限码集合框架来校验这个集合中是否包含指定的权限码。 例如当前账号拥有权限码集合 [user-add, user-delete, user-get]这时候我来校验权限 user-update则其结果就是验证失败禁止访问。 所以现在问题的核心就是 如何获取一个账号所拥有的的权限码集合 本次操作需要验证的权限码是哪个 获取当前账号权限码集合 因为每个项目的需求不同其权限设计也千变万化因此 [ 获取当前账号权限码集合 ] 这一操作不可能内置到框架中 所以Sa-Token将此操作以接口的方式暴露给你以方便你根据自己的业务逻辑进行重写。 你需要做的就是新建一个类实现StpInterface接口例如以下代码 /*** 自定义权限验证接口扩展 */ Component // 保证此类被SpringBoot扫描完成Sa-Token的自定义权限验证扩展 public class StpInterfaceImpl implements StpInterface {/*** 返回一个账号所拥有的权限码集合 */Overridepublic ListString getPermissionList(Object loginId, String loginType) {// 本list仅做模拟实际项目中要根据具体业务逻辑来查询权限ListString list new ArrayListString(); list.add(101);list.add(user-add);list.add(user-delete);list.add(user-update);list.add(user-get);list.add(article-get);return list;}/*** 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验)*/Overridepublic ListString getRoleList(Object loginId, String loginType) {// 本list仅做模拟实际项目中要根据具体业务逻辑来查询角色ListString list new ArrayListString(); list.add(admin);list.add(super-admin);return list;}} 参数解释 loginId账号id即你在调用StpUtil.login(id)时写入的标识值。 loginType账号体系标识 权限认证 然后就可以用以下api来鉴权了 // 获取当前账号所拥有的权限集合 StpUtil.getPermissionList();// 判断当前账号是否含有指定权限, 返回true或false StpUtil.hasPermission(user-update); // 校验当前账号是否含有指定权限, 如果验证未通过则抛出异常: NotPermissionException StpUtil.checkPermission(user-update); // 校验当前账号是否含有指定权限 [指定多个必须全部验证通过] StpUtil.checkPermissionAnd(user-update, user-delete); // 校验当前账号是否含有指定权限 [指定多个只要其一验证通过即可] StpUtil.checkPermissionOr(user-update, user-delete); 扩展NotPermissionException对象可通过getLoginType()方法获取具体是哪个StpLogic抛出的异常 角色认证 在Sa-Token中角色和权限可以独立验证 // 获取当前账号所拥有的角色集合 StpUtil.getRoleList();// 判断当前账号是否拥有指定角色, 返回true或false StpUtil.hasRole(super-admin); // 校验当前账号是否含有指定角色标识, 如果验证未通过则抛出异常: NotRoleException StpUtil.checkRole(super-admin); // 校验当前账号是否含有指定角色标识 [指定多个必须全部验证通过] StpUtil.checkRoleAnd(super-admin, shop-admin); // 校验当前账号是否含有指定角色标识 [指定多个只要其一验证通过即可] StpUtil.checkRoleOr(super-admin, shop-admin); 扩展NotRoleException对象可通过getLoginType()方法获取具体是哪个StpLogic抛出的异常 拦截全局异常 有同学要问鉴权失败抛出异常然后呢要把异常显示给用户看吗当然不可以 你可以创建一个全局异常拦截器统一返回给前端的格式参考 RestControllerAdvice public class GlobalExceptionHandler {// 全局异常拦截 ExceptionHandlerpublic SaResult handlerException(Exception e) {e.printStackTrace(); return SaResult.error(e.getMessage());} } 权限通配符 Sa-Token允许你根据通配符指定泛权限例如当一个账号拥有user*的权限时user-add、user-delete、user-update都将匹配通过 // 当拥有 user* 权限时 StpUtil.hasPermission(user-add); // true StpUtil.hasPermission(user-update); // true StpUtil.hasPermission(art-add); // false// 当拥有 *-delete 权限时 StpUtil.hasPermission(user-add); // false StpUtil.hasPermission(user-delete); // true StpUtil.hasPermission(art-delete); // true// 当拥有 *.js 权限时 StpUtil.hasPermission(index.js); // true StpUtil.hasPermission(index.css); // false StpUtil.hasPermission(index.html); // false 上帝权限当一个账号拥有 * 权限时他可以验证通过任何权限码 角色认证同理 如何把权限精确到按钮级 权限精确到按钮级的意思就是指权限范围可以控制到页面上的每一个按钮是否显示。 “ 思路如此精确的范围控制只依赖后端已经难以完成此时需要前端进行一定的逻辑判断。 如果是前后端分离项目则 在登录时把当前账号拥有的所有权限码一次性返回给前端。 前端将权限码集合保存在localStorage或其它全局状态管理对象中。 在需要权限控制的按钮上使用 js 进行逻辑判断例如在Vue框架中我们可以使用如是写法 button v-ifarr.indexOf(user:delete) -1删除按钮/button 其中arr是当前用户拥有的权限码数组user:delete是显示按钮需要拥有的权限码删除按钮是用户拥有权限码才可以看到的内容。 “ 注意以上写法只为提供一个参考示例不同框架有不同写法大家可根据项目技术栈灵活封装进行调用。 前端有了鉴权后端还需要鉴权吗 需要 前端的鉴权只是一个辅助功能对于专业人员这些限制都是可以轻松绕过的为保证服务器安全无论前端是否进行了权限校验后端接口都需要对会话请求再次进行权限校验 2. 功能一览 上述只提供了登录认证和权限认证的两个功能Sa-Token还有如下诸多功能 登录认证 —— 单端登录、多端登录、同端互斥登录、七天内免登录 权限认证 —— 权限认证、角色认证、会话二级认证 Session会话 —— 全端共享Session、单端独享Session、自定义Session 踢人下线 —— 根据账号id踢人下线、根据Token值踢人下线 账号封禁 —— 指定天数封禁、永久封禁、设定解封时间 持久层扩展 —— 可集成Redis、Memcached等专业缓存中间件重启数据不丢失 分布式会话 —— 提供jwt集成、共享数据中心两种分布式会话方案 微服务网关鉴权 —— 适配Gateway、ShenYu、Zuul等常见网关的路由拦截认证 单点登录 —— 内置三种单点登录模式无论是否跨域、是否共享Redis都可以搞定 OAuth2.0认证 —— 基于RFC-6749标准编写OAuth2.0标准流程的授权认证支持openid模式 二级认证 —— 在已登录的基础上再次认证保证安全性 Basic认证 —— 一行代码接入Http Basic认证 独立Redis —— 将权限缓存与业务缓存分离 临时Token验证 —— 解决短时间的Token授权问题 模拟他人账号 —— 实时操作任意用户状态数据 临时身份切换 —— 将会话身份临时切换为其它账号 前后台分离 —— APP、小程序等不支持Cookie的终端 同端互斥登录 —— 像QQ一样手机电脑同时在线但是两个手机上互斥登录 多账号认证体系 —— 比如一个商城项目的user表和admin表分开鉴权 花式token生成 —— 内置六种Token风格还可自定义Token生成策略、自定义Token前缀 注解式鉴权 —— 优雅的将鉴权与业务代码分离 路由拦截式鉴权 —— 根据路由拦截鉴权可适配restful模式 自动续签 —— 提供两种Token过期策略灵活搭配使用还可自动续签 会话治理 —— 提供方便灵活的会话查询接口 记住我模式 —— 适配[记住我]模式重启浏览器免验证 密码加密 —— 提供密码加密模块可快速MD5、SHA1、SHA256、AES、RSA加密 全局侦听器 —— 在用户登陆、注销、被踢下线等关键性操作时进行一些AOP操作 开箱即用 —— 提供SpringMVC、WebFlux等常见web框架starter集成包真正的开箱即用 3. Sa-Token使用 3.1 引入Sa-Token依赖 Maven或 Gradle依赖 !-- Sa-Token 权限认证, 在线文档http://sa-token.dev33.cn/ -- dependencygroupIdcn.dev33/groupIdartifactIdsa-token-spring-boot-starter/artifactIdversion1.30.0/version /dependency!-- Gradle 依赖 -- implementation cn.dev33:sa-token-spring-boot-starter:1.30.0 3.2 Sa-Token源码 源码下载 “ Gitee地址https://gitee.com/dromara/sa-token “ GitHub地址https://github.com/dromara/sa-token 源码目录 ── sa-token├── sa-token-core // [核心] Sa-Token 核心模块├── sa-token-starter // [整合] Sa-Token 与其它框架整合├── sa-token-servlet // [整合] Sa-Token 整合 Servlet容器实现类包├── sa-token-spring-boot-starter // [整合] Sa-Token 整合 SpringBoot 快速集成 ├── sa-token-reactor-spring-boot-starter // [整合] Sa-Token 整合 Reactor 响应式编程 快速集成 ├── sa-token-solon-plugin // [整合] Sa-Token 整合 Solon 快速集成 ├── sa-token-jfinal-plugin // [整合] Sa-Token 整合 JFinal 快速集成 ├── sa-token-jboot-plugin // [整合] Sa-Token 整合 jboot 快速集成 ├── sa-token-plugin // [插件] Sa-Token 插件合集├── sa-token-dao-redis // [插件] Sa-Token 整合 Redis (使用jdk默认序列化方式)├── sa-token-dao-redis-jackson // [插件] Sa-Token 整合 Redis (使用jackson序列化方式)├── sa-token-spring-aop // [插件] Sa-Token 整合 SpringAOP 注解鉴权├── sa-token-temp-jwt // [插件] Sa-Token 整合 jwt 临时令牌鉴权 ├── sa-token-quick-login // [插件] Sa-Token 快速注入登录页插件 ├── sa-token-alone-redis // [插件] Sa-Token 独立Redis插件实现[权限缓存与业务缓存分离]├── sa-token-sso // [插件] Sa-Token 整合 SSO 单点登录├── sa-token-oauth2 // [插件] Sa-Token 实现 OAuth2.0 模块 ├── sa-token-dialect-thymeleaf // [插件] Sa-Token 标签方言Thymeleaf版├── sa-token-jwt // [插件] Sa-Token 整合 jwt 登录认证├── sa-token-demo // [示例] Sa-Token 示例合集├── sa-token-demo-springboot // [示例] Sa-Token 整合 SpringBoot ├── sa-token-demo-springboot-redis // [示例] Sa-Token 整合 SpringBoot ├── sa-token-demo-webflux // [示例] Sa-Token 整合 WebFlux ├── sa-token-demo-jwt // [示例] Sa-Token 集成 jwt ├── sa-token-demo-solon // [示例] Sa-Token 集成 Solon ├── sa-token-demo-quick-login // [示例] Sa-Token 集成 quick-login 模块 ├── sa-token-demo-alone-redis // [示例] Sa-Token 集成 alone-redis 模块├── sa-token-demo-thymeleaf // [示例] Sa-Token 集成 Thymeleaf 标签方言├── sa-token-demo-jwt // [示例] Sa-Token 集成 jwt 登录认证 ├── sa-token-demo-sso-server // [示例] Sa-Token 集成 SSO单点登录-Server认证中心├── sa-token-demo-sso1-client // [示例] Sa-Token 集成 SSO单点登录-模式一 应用端 ├── sa-token-demo-sso2-client // [示例] Sa-Token 集成 SSO单点登录-模式二 应用端├── sa-token-demo-sso3-client // [示例] Sa-Token 集成 SSO单点登录-模式三 应用端├── sa-token-demo-sso3-client-nosdk // [示例] Sa-Token 集成 SSO单点登录-模式三 应用端 (不使用sdk纯手动对接)├── sa-token-demo-sso-server-h5 // [示例] Sa-Token 集成 SSO单点登录-Server认证中心 (前后端分离)├── sa-token-demo-sso-client-h5 // [示例] Sa-Token 集成 SSO单点登录-client应用端 (前后端分离)├── sa-token-demo-oauth2-server // [示例] Sa-Token 集成 OAuth2.0 (服务端)├── sa-token-demo-oauth2-client // [示例] Sa-Token 集成 OAuth2.0 (客户端)├── sa-token-demo-websocket // [示例] Sa-Token 集成 Web-Socket 鉴权示例├── sa-token-demo-websocket-spring // [示例] Sa-Token 集成 Web-SocketSpring封装版 鉴权示例├── sa-token-test // [测试] Sa-Token 单元测试合集├── sa-token-core-test // [测试] Sa-Token Core核心包单元测试├── sa-token-springboot-test // [测试] Sa-Token SpringBoot 整合测试├── sa-token-springboot-integrate-test // [测试] Sa-Token SpringBoot 整合客户端测试├── sa-token-jwt-test // [测试] Sa-Token jwt 整合测试├── sa-token-doc // [文档] Sa-Token 开发文档 ├──pom.xml // [依赖] 顶级pom文件 3.3 SpringBoot集成Sa-Token示例 创建项目 在IDE中新建一个SpringBoot项目例如sa-token-demo-springboot 添加依赖 在pom.xml中添加依赖 !-- Sa-Token 权限认证, 在线文档http://sa-token.dev33.cn/ -- dependencygroupIdcn.dev33/groupIdartifactIdsa-token-spring-boot-starter/artifactIdversion1.30.0/version /dependency 设置配置文件 你可以零配置启动项目 但同时你也可以在 application.yml 中增加如下配置定制性使用框架 server:## 端口port: 8081## Sa-Token配置 sa-token: ## token 名称 (同时也是cookie名称)token-name: satoken## token 有效期单位s 默认30天, -1代表永不过期 timeout: 2592000## token 临时有效期 (指定时间内无操作就视为token过期) 单位: 秒activity-timeout: -1## 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) is-concurrent: true## 在多人登录同一账号时是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token) is-share: false## token风格token-style: uuid## 是否输出操作日志 is-log: false 创建启动类 在项目中新建包com.pj在此包内新建主类 SaTokenDemoApplication.java复制以下代码 SpringBootApplication public class SaTokenDemoApplication {public static void main(String[] args) throws JsonProcessingException {SpringApplication.run(SaTokenDemoApplication.class, args);System.out.println(启动成功Sa-Token配置如下 SaManager.getConfig());} } 创建测试Controller RestController RequestMapping(/user/) public class UserController {// 测试登录浏览器访问http://localhost:8081/user/doLogin?usernamezhangpassword123456RequestMapping(doLogin)public String doLogin(String username, String password) {// 此处仅作模拟示例真实项目需要从数据库中查询数据进行比对 if(zhang.equals(username) 123456.equals(password)) {StpUtil.login(10001);return 登录成功;}return 登录失败;}// 查询登录状态浏览器访问http://localhost:8081/user/isLoginRequestMapping(isLogin)public String isLogin() {return 当前会话是否登录 StpUtil.isLogin();}} 运行测试  3.4 Spring WebFlux集成Sa-Token示例 Reactor是一种非阻塞的响应式模型以WebFlux 为例来展示Sa-Token与Reactor响应式模型框架相整合的示例 你可以用同样方式去对接其它 Reactor模型框架Netty、ShenYu、SpringCloud Gateway等 整合示例在官方仓库的/sa-token-demo/sa-token-demo-webflux文件夹下如遇到难点可结合源码进行测试学习 WebFlux 用于微服务网关架构中如果您的应用基于单体架构且非Reactor 模型 创建项目 在IDE中新建一个SpringBoot项目例如sa-token-demo-webflux 添加依赖 在pom.xml中添加依赖 !-- Sa-Token 权限认证Reactor响应式集成, 在线文档http://sa-token.dev33.cn/ -- dependencygroupIdcn.dev33/groupIdartifactIdsa-token-reactor-spring-boot-starter/artifactIdversion1.30.0/version /dependency 创建启动类 在项目中新建包com.pj在此包内新建主类 SaTokenDemoApplication.java输入以下代码  SpringBootApplication public class SaTokenDemoApplication {public static void main(String[] args) throws JsonProcessingException {SpringApplication.run(SaTokenDemoApplication.class, args);System.out.println(启动成功Sa-Token配置如下 SaManager.getConfig());} } 创建全局过滤器 新建SaTokenConfigure.java注册Sa-Token的全局过滤器 /*** [Sa-Token 权限认证] 全局配置类 */ Configuration public class SaTokenConfigure {/*** 注册 [Sa-Token全局过滤器] */Beanpublic SaReactorFilter getSaReactorFilter() {return new SaReactorFilter()// 指定 [拦截路由].addInclude(/**)// 指定 [放行路由].addExclude(/favicon.ico)// 指定[认证函数]: 每次请求执行 .setAuth(obj - {System.out.println(---------- sa全局认证);// SaRouter.match(/test/test, () - StpUtil.checkLogin());})// 指定[异常处理函数]每次[认证函数]发生异常时执行此函数 .setError(e - {System.out.println(---------- sa全局异常 );return SaResult.error(e.getMessage());});} } 你只需要按照此格式复制代码即可。 创建测试Controller RestController RequestMapping(/user/) public class UserController {// 测试登录浏览器访问http://localhost:8081/user/doLogin?usernamezhangpassword123456RequestMapping(doLogin)public String doLogin(String username, String password) {// 此处仅作模拟示例真实项目需要从数据库中查询数据进行比对 if(zhang.equals(username) 123456.equals(password)) {StpUtil.login(10001);return 登录成功;}return 登录失败;}// 查询登录状态浏览器访问http://localhost:8081/user/isLoginRequestMapping(isLogin)public String isLogin() {return 当前会话是否登录 StpUtil.isLogin();}} 浏览器运行测试 4.总结 Sa-Token框架是一个轻量级的登录、鉴权框架有利于我们开发。
http://www.yingshimen.cn/news/91906/

相关文章:

  • 智能营销型网站制作seo是啥职位
  • 乐清市网站建设设计wordpress迁移域名修改
  • 绝味鸭脖网站建设规划书遵义网站建设gzyhg
  • o2o电商网站建设网站外部优化
  • 网站开发建设协议医疗器械研发
  • 做的比较早的海淘网站小微宝安网站建设
  • 福州网站制作设计wordpress 投票网站
  • 菜谱网站后台代码wordpress 简单 免费主题下载
  • 阿里云建站论坛网站详情页怎么做
  • 网站设计与建设公司芜湖网站 建设
  • app设计的基本流程杭州百家号优化
  • 网站底部备案代码网站背景尺寸
  • 网站建设郑州公司芷江建设工程招投标网站
  • 库车建设工程信息网站云南建管微信小程序
  • 建设网站费用做影视网站怎么赚钱
  • 做网站用什么服务器会比较好唐山哪里建地铁
  • 南阳seo网站价格上海建筑建材业信息网
  • 显示危险网站怎么解决wordpress新手技巧
  • 做淘客的网站都有哪几个网站建设一般要多少费用
  • 扬州市网站建设工作室策划营销方案
  • 网站建设网站形象网页设计的目的与要求
  • 用微信怎么做企业网站网站链接交易
  • 如何自己做网站卖东西推荐 网页游戏
  • 网站开发专业都有哪些课程网页制作师培训
  • wap企业网站wordpress没有描述
  • 政务公开网站建设方案如何做好集团网站建设
  • 国内产品网站1688路由下做网站映射
  • 建设网站培训班八年级学生做的简易网站
  • 网站落地页如何做c 语言可以做网站吗
  • 丽水做网站公司江西省都昌县建设局网站