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

沧州做网站aso优化方案

沧州做网站,aso优化方案,网站设计服务,wordpress首页被篡改Sa-Token 单体架构使用实战 官网地址:https://sa-token.cc/ 在项目开发中,我曾因 SpringSecurity 和 Shiro 的复杂性及文档理解难度而困扰,国产安全框架 Sa-Token 很好地解决了权限认证相关问题,确实为开发工作提供了诸多便利。…

Sa-Token 单体架构使用实战

官网地址:https://sa-token.cc/

在项目开发中,我曾因 SpringSecurity 和 Shiro 的复杂性及文档理解难度而困扰,国产安全框架 Sa-Token 很好地解决了权限认证相关问题,确实为开发工作提供了诸多便利。官方文档已对框架功能和配置进行了详尽说明,若您在使用中遇到配置或概念疑问,建议优先查阅官方文档。此手册主要用于记录 SpringBoot 单体架构下管理后台的实战开发过程,希望能为您提供一些参考。

项目前端代码可通过以下链接查阅:Vue3后台管理系统

数据库表结构设计

在这里插入图片描述

  • 一个用户拥有多个角色
  • 一个角色拥有多个菜单权限
  • 创建用户角色关系表 通过用户id查询到角色列表
  • 创建角色权限关系表 通过角色id查询到权限列表
  • 通过上述关系即可通过用户id查询到权限列表进行权限控制
CREATE DATABASE `management` CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_0900_ai_ci';
CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',`username` varchar(255) NOT NULL COMMENT '用户名',`password` varchar(255) NOT NULL COMMENT '密码',`nickname` varchar(255) DEFAULT NULL COMMENT '昵称',`avatar` varchar(255) DEFAULT NULL COMMENT '头像',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',`is_delete` int(1) DEFAULT '0' COMMENT '是否删除 0-否 1-是',PRIMARY KEY (`id`)
) ENGINE=InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户表';
CREATE TABLE `role` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',`name` varchar(255) DEFAULT NULL COMMENT '角色名',`tag` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '角色标识',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',`is_delete` int(1) DEFAULT '0' COMMENT '是否删除 0-否 1-是',PRIMARY KEY (`id`)
) ENGINE=InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='角色表';
CREATE TABLE `menu` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',`name` varchar(255) DEFAULT NULL COMMENT '权限名称',`acl` varchar(255) DEFAULT NULL COMMENT '权限值',`parent_id` int(11) DEFAULT NULL COMMENT '上级id',`level` int(11) DEFAULT NULL COMMENT '层级',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',`is_delete` int(1) DEFAULT '0' COMMENT '是否删除 0-否 1-是',PRIMARY KEY (`id`)
) ENGINE=InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='菜单权限表';
CREATE TABLE `user_role_relation` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',`user_id` int(11) DEFAULT NULL COMMENT '用户id',`role_id` int(11) DEFAULT NULL COMMENT '角色id',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',`is_delete` int(1) DEFAULT '0' COMMENT '是否删除 0-否 1-是',PRIMARY KEY (`id`)
) ENGINE=InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户和角色对应关系表';
CREATE TABLE `menu_role_relation` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',`menu_id` int(11) DEFAULT NULL COMMENT '权限id',`role_id` int(11) DEFAULT NULL COMMENT '角色名称',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',`is_delete` int(1) DEFAULT '0' COMMENT '是否删除 0-否 1-是',PRIMARY KEY (`id`)
) ENGINE=InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='菜单权限和角色对应关系表';

数据库初始化脚本

INSERT INTO `management`.`user` (`id`, `username`, `password`, `nickname`, `avatar`, `create_time`, `update_time`, `is_delete`) VALUES (1, 'admin', '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92', '超级管理员', 'http://47.121.182.69:9000/management/avatar1.jpg', '2025-04-02 15:00:44', '2025-06-04 15:45:57', 0);INSERT INTO `management`.`role` (`id`, `name`, `key`, `create_time`, `update_time`, `is_delete`) VALUES (1, '老板', 'Boss', '2025-04-01 16:51:21', '2025-04-02 16:41:16', 0);INSERT INTO `management`.`user_role_relation` (`id`, `user_id`, `role_id`, `create_time`, `update_time`, `is_delete`) VALUES (1, 1, 1, '2025-04-16 15:49:13', '2025-04-16 15:49:13', 0);INSERT INTO `management`.`menu` (`id`, `name`, `acl`, `parent_id`, `level`, `create_time`, `update_time`, `is_delete`) VALUES (1, '全部数据', NULL, 0, 0, '2025-04-03 16:05:13', '2025-04-03 17:09:54', 0);
INSERT INTO `management`.`menu` (`id`, `name`, `acl`, `parent_id`, `level`, `create_time`, `update_time`, `is_delete`) VALUES (2, '权限管理', 'ACL', 1, 1, '2025-04-03 16:08:43', '2025-04-07 11:23:16', 0);
INSERT INTO `management`.`menu` (`id`, `name`, `acl`, `parent_id`, `level`, `create_time`, `update_time`, `is_delete`) VALUES (3, '用户管理', 'User', 2, 2, '2025-04-03 16:09:15', '2025-04-03 16:09:17', 0);
INSERT INTO `management`.`menu` (`id`, `name`, `acl`, `parent_id`, `level`, `create_time`, `update_time`, `is_delete`) VALUES (4, '角色管理', 'Role', 2, 2, '2025-04-03 16:09:15', '2025-04-03 16:09:17', 0);
INSERT INTO `management`.`menu` (`id`, `name`, `acl`, `parent_id`, `level`, `create_time`, `update_time`, `is_delete`) VALUES (5, '菜单管理', 'Menu', 2, 2, '2025-04-03 17:19:11', '2025-04-03 17:19:13', 0);
INSERT INTO `management`.`menu` (`id`, `name`, `acl`, `parent_id`, `level`, `create_time`, `update_time`, `is_delete`) VALUES (6, '添加用户', 'btn.addUser', 3, 3, '2025-04-07 16:26:02', '2025-04-07 16:59:09', 0);
INSERT INTO `management`.`menu` (`id`, `name`, `acl`, `parent_id`, `level`, `create_time`, `update_time`, `is_delete`) VALUES (7, '编辑用户', 'btn.editUser', 3, 3, '2025-04-08 11:24:29', '2025-04-08 11:24:33', 0);
INSERT INTO `management`.`menu` (`id`, `name`, `acl`, `parent_id`, `level`, `create_time`, `update_time`, `is_delete`) VALUES (8, '删除用户', 'btn.deleteUser', 3, 3, '2025-04-08 11:24:29', '2025-04-08 11:24:33', 0);
INSERT INTO `management`.`menu` (`id`, `name`, `acl`, `parent_id`, `level`, `create_time`, `update_time`, `is_delete`) VALUES (9, '批量删除用户', 'btn.batchDeleteUser', 3, 3, '2025-04-08 11:24:29', '2025-04-08 11:24:33', 0);
INSERT INTO `management`.`menu` (`id`, `name`, `acl`, `parent_id`, `level`, `create_time`, `update_time`, `is_delete`) VALUES (10, '分配角色', 'btn.allocateRole', 3, 3, '2025-04-07 16:26:02', '2025-04-07 16:59:09', 0);
INSERT INTO `management`.`menu` (`id`, `name`, `acl`, `parent_id`, `level`, `create_time`, `update_time`, `is_delete`) VALUES (11, '添加角色', 'btn.addRole', 4, 3, '2025-04-08 11:28:30', '2025-04-08 11:28:32', 0);
INSERT INTO `management`.`menu` (`id`, `name`, `acl`, `parent_id`, `level`, `create_time`, `update_time`, `is_delete`) VALUES (12, '编辑角色', 'btn.editRole', 4, 3, '2025-04-08 11:28:30', '2025-04-08 11:28:32', 0);
INSERT INTO `management`.`menu` (`id`, `name`, `acl`, `parent_id`, `level`, `create_time`, `update_time`, `is_delete`) VALUES (13, '删除角色', 'btn.deleteRole', 4, 3, '2025-04-08 11:28:30', '2025-04-08 11:28:32', 0);
INSERT INTO `management`.`menu` (`id`, `name`, `acl`, `parent_id`, `level`, `create_time`, `update_time`, `is_delete`) VALUES (14, '分配权限', 'btn.allocateACL', 4, 3, '2025-04-08 11:28:30', '2025-04-08 11:28:32', 0);
INSERT INTO `management`.`menu` (`id`, `name`, `acl`, `parent_id`, `level`, `create_time`, `update_time`, `is_delete`) VALUES (15, '添加菜单', 'btn.addMenu', 5, 3, '2025-04-08 11:28:30', '2025-04-08 11:28:32', 0);
INSERT INTO `management`.`menu` (`id`, `name`, `acl`, `parent_id`, `level`, `create_time`, `update_time`, `is_delete`) VALUES (16, '编辑菜单', 'btn.editMenu', 5, 3, '2025-04-08 11:28:30', '2025-04-08 11:28:32', 0);
INSERT INTO `management`.`menu` (`id`, `name`, `acl`, `parent_id`, `level`, `create_time`, `update_time`, `is_delete`) VALUES (17, '删除菜单', 'btn.deleteMenu', 5, 3, '2025-04-08 11:28:30', '2025-04-08 11:28:32', 0);
INSERT INTO `management`.`menu` (`id`, `name`, `acl`, `parent_id`, `level`, `create_time`, `update_time`, `is_delete`) VALUES (18, '查询用户', 'btn.queryUser', 3, 3, '2025-04-16 15:55:06', '2025-04-16 15:55:06', 0);
INSERT INTO `management`.`menu` (`id`, `name`, `acl`, `parent_id`, `level`, `create_time`, `update_time`, `is_delete`) VALUES (19, '查询角色', 'btn.queryRole', 4, 3, '2025-04-16 15:56:45', '2025-04-16 15:56:45', 0);
INSERT INTO `management`.`menu` (`id`, `name`, `acl`, `parent_id`, `level`, `create_time`, `update_time`, `is_delete`) VALUES (20, '查询菜单', 'btn.queryMenu', 5, 3, '2025-04-16 15:57:03', '2025-04-16 15:57:03', 0);INSERT INTO `management`.`menu_role_relation` (`id`, `menu_id`, `role_id`, `create_time`, `update_time`, `is_delete`) VALUES (1, 1, 1, '2025-04-17 09:27:45', '2025-04-17 09:27:52', 0);
INSERT INTO `management`.`menu_role_relation` (`id`, `menu_id`, `role_id`, `create_time`, `update_time`, `is_delete`) VALUES (2, 2, 1, '2025-04-17 09:27:45', '2025-04-17 09:27:52', 0);
INSERT INTO `management`.`menu_role_relation` (`id`, `menu_id`, `role_id`, `create_time`, `update_time`, `is_delete`) VALUES (3, 3, 1, '2025-04-17 09:27:45', '2025-04-17 09:27:52', 0);
INSERT INTO `management`.`menu_role_relation` (`id`, `menu_id`, `role_id`, `create_time`, `update_time`, `is_delete`) VALUES (4, 4, 1, '2025-04-17 09:27:45', '2025-04-17 09:27:52', 0);
INSERT INTO `management`.`menu_role_relation` (`id`, `menu_id`, `role_id`, `create_time`, `update_time`, `is_delete`) VALUES (5, 5, 1, '2025-04-17 09:27:45', '2025-04-17 09:27:52', 0);
INSERT INTO `management`.`menu_role_relation` (`id`, `menu_id`, `role_id`, `create_time`, `update_time`, `is_delete`) VALUES (6, 6, 1, '2025-04-17 09:27:45', '2025-04-17 09:27:52', 0);
INSERT INTO `management`.`menu_role_relation` (`id`, `menu_id`, `role_id`, `create_time`, `update_time`, `is_delete`) VALUES (7, 7, 1, '2025-04-17 09:27:45', '2025-04-17 09:27:52', 0);
INSERT INTO `management`.`menu_role_relation` (`id`, `menu_id`, `role_id`, `create_time`, `update_time`, `is_delete`) VALUES (8, 8, 1, '2025-04-17 09:27:45', '2025-04-17 09:27:52', 0);
INSERT INTO `management`.`menu_role_relation` (`id`, `menu_id`, `role_id`, `create_time`, `update_time`, `is_delete`) VALUES (9, 9, 1, '2025-04-17 09:27:45', '2025-04-17 09:27:52', 0);
INSERT INTO `management`.`menu_role_relation` (`id`, `menu_id`, `role_id`, `create_time`, `update_time`, `is_delete`) VALUES (10, 10, 1, '2025-04-17 09:27:45', '2025-04-17 09:27:52', 0);
INSERT INTO `management`.`menu_role_relation` (`id`, `menu_id`, `role_id`, `create_time`, `update_time`, `is_delete`) VALUES (11, 11, 1, '2025-04-17 09:27:45', '2025-04-17 09:27:52', 0);
INSERT INTO `management`.`menu_role_relation` (`id`, `menu_id`, `role_id`, `create_time`, `update_time`, `is_delete`) VALUES (12, 12, 1, '2025-04-17 09:27:45', '2025-04-17 09:27:52', 0);
INSERT INTO `management`.`menu_role_relation` (`id`, `menu_id`, `role_id`, `create_time`, `update_time`, `is_delete`) VALUES (13, 13, 1, '2025-04-17 09:27:45', '2025-04-17 09:27:52', 0);
INSERT INTO `management`.`menu_role_relation` (`id`, `menu_id`, `role_id`, `create_time`, `update_time`, `is_delete`) VALUES (14, 14, 1, '2025-04-17 09:27:45', '2025-04-17 09:27:52', 0);
INSERT INTO `management`.`menu_role_relation` (`id`, `menu_id`, `role_id`, `create_time`, `update_time`, `is_delete`) VALUES (15, 15, 1, '2025-04-17 09:27:45', '2025-04-17 09:27:52', 0);
INSERT INTO `management`.`menu_role_relation` (`id`, `menu_id`, `role_id`, `create_time`, `update_time`, `is_delete`) VALUES (16, 16, 1, '2025-04-17 09:27:45', '2025-04-17 09:27:52', 0);
INSERT INTO `management`.`menu_role_relation` (`id`, `menu_id`, `role_id`, `create_time`, `update_time`, `is_delete`) VALUES (17, 17, 1, '2025-04-17 09:27:45', '2025-04-17 09:27:52', 0);
INSERT INTO `management`.`menu_role_relation` (`id`, `menu_id`, `role_id`, `create_time`, `update_time`, `is_delete`) VALUES (18, 18, 1, '2025-04-17 09:27:45', '2025-04-17 09:27:52', 0);
INSERT INTO `management`.`menu_role_relation` (`id`, `menu_id`, `role_id`, `create_time`, `update_time`, `is_delete`) VALUES (19, 19, 1, '2025-04-17 09:27:45', '2025-04-17 09:27:52', 0);
INSERT INTO `management`.`menu_role_relation` (`id`, `menu_id`, `role_id`, `create_time`, `update_time`, `is_delete`) VALUES (20, 20, 1, '2025-04-17 09:27:45', '2025-04-17 09:27:52', 0);

权限认证

引入 Sa-Token

<!-- Sa-Token 权限认证 -->
<dependency><groupId>cn.dev33</groupId><artifactId>sa-token-spring-boot3-starter</artifactId><version>1.44.0</version>
</dependency>
<!-- Sa-Token 集成 Redis -->
<dependency><groupId>cn.dev33</groupId><artifactId>sa-token-redis-template</artifactId><version>1.44.0</version>
</dependency>
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId>
</dependency>
<!-- Sa-Token 集成 JWT -->
<dependency><groupId>cn.dev33</groupId><artifactId>sa-token-jwt</artifactId><version>1.44.0</version>
</dependency>

配置文件

server:port: 8082
spring:datasource:url: jdbc:mysql://127.0.0.1:3306/managementusername: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driverdata:redis:port: 6379host: 127.0.0.1password: 123456database: 0
sa-token:# jwt 的秘钥jwt-secret-key: # token 的名字token-name: token# 是否打印日志is-log: true# 是否生成同一个 tokenis-share: true# 是否可以同时登录is-concurrent: false

通过逆向工程生成的 mybatis 文件此处省略

查询用户权限的接口

public interface UserService extends IService<User> {// 根据用户id 获取用户角色标识集合List<RoleVO> getRoleListByUserId(Integer userId);// 根据用户id 获取用户权限集合List<Menu> getACLListByUserId(Integer userId);// 菜单路径权限List<String> getRouteList(List<Menu> menuList);// 按钮权限List<String> getButtonList(List<Menu> menuList);
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {@Autowiredprivate RoleService roleService;@Autowiredprivate UserRoleRelationService userRoleRelationService;@Autowiredprivate MenuService menuService;@Autowiredprivate MenuRoleRelationService menuRoleRelationService;@Overridepublic List<RoleVO> getRoleListByUserId(Integer userId) {List<RoleVO> roles = new ArrayList<>();List<UserRoleRelation> userRoleRelations = userRoleRelationService.list(new LambdaQueryWrapper<UserRoleRelation>().eq(UserRoleRelation::getUserId, userId));if (CollectionUtil.isNotEmpty(userRoleRelations)) {List<Integer> roleIdList = userRoleRelations.stream().map(UserRoleRelation::getRoleId).toList();List<Role> roleList = roleService.list(new LambdaQueryWrapper<Role>().in(Role::getId, roleIdList));roles = BeanUtil.copyToList(roleList, RoleVO.class);}return roles;}@Overridepublic List<Menu> getACLListByUserId(Integer userId) {List<Menu> menuList = new ArrayList<>();// 设置 buttons routesList<UserRoleRelation> userRoleRelations = userRoleRelationService.list(new LambdaQueryWrapper<UserRoleRelation>().eq(UserRoleRelation::getUserId, userId));// 获取角色idList<Integer> roleIds = userRoleRelations.stream().map(UserRoleRelation::getRoleId).toList();if (CollectionUtil.isNotEmpty(roleIds)) {// 菜单和角色对应关系List<MenuRoleRelation> menuRoleRelations = menuRoleRelationService.list(new LambdaQueryWrapper<MenuRoleRelation>().in(MenuRoleRelation::getRoleId, roleIds));// 菜单列表List<Integer> menuIds = menuRoleRelations.stream().map(MenuRoleRelation::getMenuId).toList();if (CollectionUtil.isNotEmpty(menuIds)) {menuList = menuService.list(new LambdaQueryWrapper<Menu>().in(Menu::getId, menuIds));}}return menuList;}@Overridepublic List<String> getRouteList(List<Menu> menuList) {return menuList.stream().filter(item -> item.getLevel().equals(1) || item.getLevel().equals(2)).map(Menu::getAcl).toList();}@Overridepublic List<String> getButtonList(List<Menu> menuList) {return menuList.stream().filter(item -> item.getLevel().equals(3)).map(Menu::getAcl).toList();}
}

将权限列表加入配置

创建文件 SaTokenPermission

@Component
public class SaTokenPermission implements StpInterface {@Autowiredprivate UserService userService;@Overridepublic List<String> getPermissionList(Object loginId, String loginType) {Integer userId = Integer.parseInt(String.valueOf(loginId));List<Menu> menuList = userService.getACLListByUserId(userId);return menuList.stream().map(Menu::getAcl).toList();}@Overridepublic List<String> getRoleList(Object loginId, String loginType) {Integer userId = Integer.parseInt(String.valueOf(loginId));List<RoleVO> roleList = userService.getRoleListByUserId(userId);return roleList.stream().map(RoleVO::getTag).toList();}
}

创建文件 SaTokenConfig

@Configuration
public class SaTokenConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注册 Sa-Token 拦截器 并放行登录接口registry.addInterceptor(new SaInterceptor(handle -> StpUtil.checkLogin())).addPathPatterns("/**").excludePathPatterns("/user/login");}// Sa-Token 整合 jwt (Simple 简单模式)@Beanpublic StpLogic getStpLogicJwt() {return new StpLogicJwtForSimple();}
}

用户接口

前后端分离项目:登录后将token信息返回。

@Tag(name = "用户管理")
@RestController
@RequestMapping("user")
public class UserController {@Autowiredprivate UserService userService;@Operation(summary = "登录")@PostMapping("login")public SaResult login(@RequestBody LoginDTO loginDTO) {String username = loginDTO.getUsername();String password = loginDTO.getPassword();User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username).eq(User::getPassword, password));if (user != null) {Integer id = user.getId();StpUtil.login(id, new SaLoginParameter().setExtra("name", user.getNickname()).setExtra("avatar", user.getAvatar()));SaTokenInfo tokenInfo = StpUtil.getTokenInfo();return SaResult.ok("登录成功").setData(tokenInfo);}return SaResult.error("登录失败");}@Operation(summary = "下线用户")@PostMapping("logout")public SaResult logout() {Integer userId = StpUtil.getLoginIdAsInt();StpUtil.logout(userId);return SaResult.ok().setData(true);}@Operation(summary = "获取用户信息")@GetMapping("info")public SaResult userInfo() {// 判断是否登录StpUtil.checkLogin();// 获取用户信息Integer userId = StpUtil.getLoginIdAsInt();User user = userService.getById(userId);UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);fillUserVO(userVO);return SaResult.ok().setData(userVO);}
}

权限注解的使用

此前通过 SaTokenPermission 已经将所有权限标识已经交给了 Sa-Token

通过 @SaCheckPermission 注解来限制接口是否能返回数据,注解的 value 为权限标识

@SaCheckPermission("btn.queryUser")
@Operation(summary = "根据id获取用户信息")
@GetMapping("getById/{id}")
public SaResult getById(@Parameter(description = "用户id")@PathVariable Integer id) {User user = userService.getById(id);UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);userVO.setRoles(userService.getRoleListByUserId(id));fillUserVO(userVO);return SaResult.ok().setData(userVO);
}
@SaCheckPermission(value = {"btn.addUser", "btn.editUser"}, mode = SaMode.OR)
@Operation(summary = "新增/修改用户信息")
@PostMapping("createOrEdit")
public SaResult createOrEdit(@RequestBody UserDTO userDTO) {User user = BeanUtil.copyProperties(userDTO, User.class);boolean result = userService.saveOrUpdate(user);return SaResult.ok().setData(result);
}

全局异常处理

当权限不足时 Sa-Token 会抛出异常,定义全局异常处理捕获异常

创建 GlobalExceptionHandler

@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandlerpublic SaResult handlerException(Exception exception) {exception.printStackTrace();return SaResult.error(exception.getMessage());}
}
http://www.dtcms.com/wzjs/98966.html

相关文章:

  • 一个虚拟主机可以放几个网站广州番禺发布
  • 浪尖工业设计公司官网短视频搜索优化
  • 做传单的网站宁波网站推广优化
  • 天水市秦州区作风建设年网站网络广告公司排名
  • 网站建设彩票网优化快速排名公司
  • 博彩网站做代理赚钱吗seo网站优化工具大全
  • it美工做网站接外贸订单的渠道平台哪个好
  • 番禺做网站平台公众号怎么开通
  • 建设网站要买服务器新华传媒b2b商务平台
  • 模具做外贸网站重庆网站建设与制作
  • 广州建站模板厂家如何网络媒体推广
  • 注册城乡规划师备考seo网络营销推广
  • 珠海网站建设官网网站外链工具
  • 深圳外贸网站建设工作室凤凰网台湾资讯
  • 长沙网站建设哪个好网络推广费用预算表
  • 正规的网站制作平台网络营销推广要求
  • 我要建立个人网站seo 优化思路
  • 网站优化软件推荐自媒体引流推广
  • 深圳做积分商城网站设计宁波网站建设方案推广
  • c 网站开发web程序快速排名软件案例
  • 网站建设行业swot分析seo价格查询公司
  • wordpress模板更改页面seo优化网站百度技术
  • 本地视频怎么生成链接seo外链收录
  • 网站程序调试模式怎么做谷歌广告推广
  • 怎么自己的电脑做网站服务器在线营销推广
  • 游戏运营备案官方网站国外免费网站域名服务器查询软件
  • 做app和网站百度账号找回
  • pandorabox做网站海南百度竞价推广
  • wordpress 获取当前文章的id厦门seo排名扣费
  • 网站建设课程ppt模板免费观看行情软件网站下载