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

如果做独立网站赚钱营销网站建设选择原则

如果做独立网站赚钱,营销网站建设选择原则,无网站网络营销,南山住房和建设局网站官网目录 需求背景 前期准备 实现UserDetailsService接口 改造loginUser 声明自定义AuthenticationManager 的bean 自定义登录接口 参考文章 效果如下 需求背景 用若依搭建的后台管理环境,但是前台用户系统(前端)并没有和若依的前端集成在一起。…

目录

需求背景

前期准备

实现UserDetailsService接口

改造loginUser

声明自定义AuthenticationManager 的bean

自定义登录接口

参考文章

效果如下

需求背景

用若依搭建的后台管理环境,但是前台用户系统(前端)并没有和若依的前端集成在一起。是两个独立的前端项目,但是后端是集成在一起的。

我现在有一个前端会员表,若依有个系统用户表,如果想要会员登录(前台用户系统)和后台登录(后台管理系统)互不干扰怎么实现(两个登录接口)?

若依分离版使用的是sping security框架,所以本质上是sping security如何实现多用户!如果你已经具备springsecurity的知识,那么你会更轻松!

明确步骤
准备:准备自定义的用户实体类,强烈建议放在common中!

1、登录时查询我们自己的表,缓存用户信息时缓存我们用户实体类型:
        实现UserDetailsService接口;
        改造loginuser类;
        自己声明AuthenticationManager 的bean;
2、自定义登录接口:
        使用我们自定义的AuthenticationManager
3、从token能够获取登录人的信息
4、前端携带token

前期准备


准备一个我们自己的用户表实体类,假设叫做CustomerUser,这个实体类再多个模块中使用,强烈建议放在common模块中!

实现UserDetailsService接口


熟悉springsecurity的都知道,登录时查询用户表是依靠UserDetailsService接口实现的,我们想要登录时查询我们自己的会员表的话,就需要实现这个接口,参照若依的UserDetailsServiceImpl,我们假定他叫CustomerDetailsServiceImpl(请定义在framework模块!建议参考若依的userSetailServiceImpl的位置

代码如下

package com.ruoyi.framework.web.service;import com.ruoyi.common.core.domain.entity.CustomerUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.UserStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.customer.mapper.CustomerUserMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;/*** 用户验证处理** @author ruoyi*/
@Component("CustomerDetailsServiceImpl")
public class CustomerDetailsServiceImpl implements UserDetailsService
{private static final Logger log = LoggerFactory.getLogger(CustomerDetailsServiceImpl.class);@Autowiredprivate CustomerUserMapper customerUserMapper;@Autowiredprivate CustomerPasswordService customerPasswordService;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{CustomerUser user = customerUserMapper.selectUserByUserName(username);if (StringUtils.isNull(user)){log.info("登录用户:{} 不存在.", username);throw new ServiceException(MessageUtils.message("user.not.exists"));}else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())){log.info("登录用户:{} 已被删除.", username);throw new ServiceException(MessageUtils.message("user.password.delete"));}else if (UserStatus.DISABLE.getCode().equals(user.getActive())){log.info("登录用户:{} 已被停用.", username);throw new ServiceException(MessageUtils.message("user.blocked"));}customerPasswordService.validate(user);return createLoginUser(user);}public UserDetails createLoginUser(CustomerUser user){return new LoginUser(user.getUserId(), user);}
}

改造loginUser

新增一个属性,CustomerUser

代码如下 

package com.ruoyi.common.core.domain.model;import com.alibaba.fastjson2.annotation.JSONField;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.entity.CustomerUser;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.Set;/*** 登录用户身份权限* * @author ruoyi*/
public class LoginUser implements UserDetails
{private static final long serialVersionUID = 1L;/*** 用户ID*/private Long userId;/*** 邀请用户ID*/private Long inviteId;/*** 部门ID*/private Long deptId;/*** 用户唯一标识*/private String token;/*** 登录时间*/private Long loginTime;/*** 过期时间*/private Long expireTime;/*** 登录IP地址*/private String ipaddr;/*** 登录地点*/private String loginLocation;/*** 浏览器类型*/private String browser;/*** 操作系统*/private String os;/*** 权限列表*/private Set<String> permissions;/*** 用户信息*/private SysUser user;/*** 客户信息*/private CustomerUser customerUser;public LoginUser(){}public LoginUser(SysUser user, Set<String> permissions){this.user = user;this.permissions = permissions;}public LoginUser(Long userId, Long deptId, SysUser user, Set<String> permissions){this.userId = userId;this.deptId = deptId;this.user = user;this.permissions = permissions;}public LoginUser(Long userId, CustomerUser user){this.userId = userId;this.customerUser = user;}public Long getUserId() { return userId; }public void setUserId(Long userId){this.userId = userId;}public Long getInviteId() { return inviteId; }public void setInviteId(Long inviteId){this.inviteId = inviteId;}public Long getDeptId(){return deptId;}public void setDeptId(Long deptId){this.deptId = deptId;}public String getToken(){return token;}public void setToken(String token){this.token = token;}@JSONField(serialize = false)@Overridepublic String getPassword(){if(user != null){return user.getPassword();}else{return customerUser.getPassword();}}@Overridepublic String getUsername(){if(user != null){return user.getUserName();}else{return customerUser.getUserName();}}/*** 账户是否未过期,过期无法验证*/@JSONField(serialize = false)@Overridepublic boolean isAccountNonExpired(){return true;}/*** 指定用户是否解锁,锁定的用户无法进行身份验证* * @return*/@JSONField(serialize = false)@Overridepublic boolean isAccountNonLocked(){return true;}/*** 指示是否已过期的用户的凭据(密码),过期的凭据防止认证* * @return*/@JSONField(serialize = false)@Overridepublic boolean isCredentialsNonExpired(){return true;}/*** 是否可用 ,禁用的用户不能身份验证* * @return*/@JSONField(serialize = false)@Overridepublic boolean isEnabled(){return true;}public Long getLoginTime(){return loginTime;}public void setLoginTime(Long loginTime){this.loginTime = loginTime;}public String getIpaddr(){return ipaddr;}public void setIpaddr(String ipaddr){this.ipaddr = ipaddr;}public String getLoginLocation(){return loginLocation;}public void setLoginLocation(String loginLocation){this.loginLocation = loginLocation;}public String getBrowser(){return browser;}public void setBrowser(String browser){this.browser = browser;}public String getOs(){return os;}public void setOs(String os){this.os = os;}public Long getExpireTime(){return expireTime;}public void setExpireTime(Long expireTime){this.expireTime = expireTime;}public Set<String> getPermissions(){return permissions;}public void setPermissions(Set<String> permissions){this.permissions = permissions;}public SysUser getUser(){ return user; }public void setUser(SysUser user){this.user = user;}public CustomerUser getCustomerUser(){ return customerUser; }public void setCustomerUser(CustomerUser customerUser) {  this.customerUser = customerUser; }@Overridepublic Collection<? extends GrantedAuthority> getAuthorities(){return null;}
}

声明自定义AuthenticationManager 的bean

原因

是这个authenticationManager调用的是若依定义的UserDetailsServiceImpl而不是我们定义的CustomerDetailsServiceImpl ,那我们怎么样才能让他调用我们定义的CustomerDetailsServiceImpl 呢?其中关键的是authenticationManager,他决定了调用哪一个

一看@Resource就知道,他注入了一个bean!那他肯定声明了这个bean!我们要找到这个AuthenticationManager的bean声明

这个AuthenticationManager用的就是若依定义的userDetailsService!

package com.ruoyi.framework.config;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.filter.CorsFilter;
import com.ruoyi.framework.config.properties.PermitAllUrlProperties;
import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter;
import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl;
import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl;/*** spring security配置* * @author ruoyi*/
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter
{/*** 自定义用户认证逻辑*/@Autowiredprivate UserDetailsService userDetailsService;/*** 自定义用户认证逻辑*/@Autowired@Qualifier("CustomerDetailsServiceImpl")private UserDetailsService customerDetailsServiceImpl;/*** 认证失败处理类*/@Autowiredprivate AuthenticationEntryPointImpl unauthorizedHandler;/*** 退出处理类*/@Autowiredprivate LogoutSuccessHandlerImpl logoutSuccessHandler;/*** token认证过滤器*/@Autowiredprivate JwtAuthenticationTokenFilter authenticationTokenFilter;/*** 跨域过滤器*/@Autowiredprivate CorsFilter corsFilter;/*** 允许匿名访问的地址*/@Autowiredprivate PermitAllUrlProperties permitAllUrl;/*** 解决 无法直接注入 AuthenticationManager** @return* @throws Exception*/@Bean@Override@Primarypublic AuthenticationManager authenticationManagerBean() throws Exception{return super.authenticationManagerBean();}@Bean("MemberAuthenticationManager")public AuthenticationManager MemberAuthenticationManagerBean() throws Exception{DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();authenticationProvider.setUserDetailsService(customerDetailsServiceImpl);// BCryptPasswordEncoder 使用BCrypt的强散列哈希加密实现,并可以由客户端指定加密的强度strength,强度越高安全性自然就越高,默认为10.BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();// authenticationProvider.setPasswordEncoder(NoOpPasswordEncoder.getInstance());//明文密码存储authenticationProvider.setPasswordEncoder(passwordEncoder);// 加密密码存储return new ProviderManager(authenticationProvider);}/*** anyRequest          |   匹配所有请求路径* access              |   SpringEl表达式结果为true时可以访问* anonymous           |   匿名可以访问* denyAll             |   用户不能访问* fullyAuthenticated  |   用户完全认证可以访问(非remember-me下自动登录)* hasAnyAuthority     |   如果有参数,参数表示权限,则其中任何一个权限可以访问* hasAnyRole          |   如果有参数,参数表示角色,则其中任何一个角色可以访问* hasAuthority        |   如果有参数,参数表示权限,则其权限可以访问* hasIpAddress        |   如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问* hasRole             |   如果有参数,参数表示角色,则其角色可以访问* permitAll           |   用户可以任意访问* rememberMe          |   允许通过remember-me登录的用户访问* authenticated       |   用户登录后可访问*/@Overrideprotected void configure(HttpSecurity httpSecurity) throws Exception{// 注解标记允许匿名访问的urlExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests();permitAllUrl.getUrls().forEach(url -> registry.antMatchers(url).permitAll());//        anonymous() 允许匿名用户访问,不允许已登入用户访问//        permitAll() 不管登入,不登入 都能访问httpSecurity// CSRF禁用,因为不使用session.csrf().disable()// 禁用HTTP响应标头.headers().cacheControl().disable().and()// 认证失败处理类.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()// 基于token,所以不需要session.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()// 过滤请求.authorizeRequests()// 对于登录login 注册register 验证码captchaImage 允许匿名访问.antMatchers("/login", "/register", "/captchaImage").permitAll().antMatchers( "/app/employee/user/employeeUserList").permitAll().antMatchers( "/employee/user/employeeUserList", "/employee/user/info/*").permitAll().antMatchers( "/system/dict/data/list").permitAll().antMatchers("/customer/info/customerLogin").permitAll()// 静态资源,可匿名访问.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll().antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()// 除上面外的所有请求全部需要鉴权认证.anyRequest().authenticated().and().headers().frameOptions().disable();// 添加Logout filterhttpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);// 添加JWT filterhttpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);// 添加CORS filterhttpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);}/*** 强散列哈希加密实现*/@Beanpublic BCryptPasswordEncoder bCryptPasswordEncoder(){return new BCryptPasswordEncoder();}/*** 身份认证接口*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception{auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());}
}

自定义登录接口


上面我们自定义了一个AuthenticationManager,并且这个AuthenticationManager指向的是我们自己的CustomerDetailsService。那我们就需要在使用这个AuthenticationManager。

package com.ruoyi.web.controller.module.customer;import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.CustomerUser;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.web.service.CustomerLoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;/*** 登录验证* * @author ruoyi*/
@RestController
@RequestMapping("/customer/info")
public class CustomerInfoController
{@Autowiredprivate CustomerLoginService customerLoginService;/*** 登录方法* * @param loginBody 登录信息* @return 结果*/@PostMapping("/customerLogin")public AjaxResult customerLogin(@RequestBody LoginBody loginBody){AjaxResult ajax = AjaxResult.success();// 生成令牌String token = customerLoginService.customerLogin(loginBody.getUsername(), loginBody.getPassword());ajax.put(Constants.TOKEN, token);return ajax;}/*** 获取用户信息** @return 用户信息*/@GetMapping("getCustomerInfo")public AjaxResult getCustomerInfo(){CustomerUser user = SecurityUtils.getLoginUser().getCustomerUser();AjaxResult ajax = AjaxResult.success();ajax.put("user", user);return ajax;}}

sevice代码

package com.ruoyi.framework.web.service;import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.user.*;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.common.core.domain.entity.CustomerUser;
import com.ruoyi.customer.service.ICustomerUserService;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.security.context.AuthenticationContextHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;import javax.annotation.Resource;/*** 登录校验方法* * @author ruoyi*/
@Component
public class CustomerLoginService
{// 是否允许账户多终端同时登录(true允许 false不允许)@Value("${token.soloLogin}")private boolean soloLogin;@Autowiredprivate RedisCache redisCache;@Resource@Qualifier("MemberAuthenticationManager")private AuthenticationManager authenticationManager;@Autowiredprivate ICustomerUserService customerUerService;@Autowiredprivate TokenService tokenService;/*** 登录验证* * @param username 用户名* @param password 密码* @return 结果*/public String customerLogin(String username, String password){// 登录前置校验loginPreCheck(username, password);CustomerUser user = null;// 用户验证Authentication authentication = null;try{UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);System.out.println("authenticationToken");System.out.println(authenticationToken);AuthenticationContextHolder.setContext(authenticationToken);// 该方法会去调用CustomerDetailsServiceImpl.loadUserByUsernamauthentication = authenticationManager.authenticate(authenticationToken);System.out.println("authentication");System.out.println(authentication);}catch (Exception e){if (e instanceof BadCredentialsException){AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));throw new UserPasswordNotMatchException();}else{AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));throw new ServiceException(e.getMessage());}}finally{AuthenticationContextHolder.clearContext();}AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));LoginUser loginUser = (LoginUser) authentication.getPrincipal();recordLoginInfo(loginUser.getUserId());if (!soloLogin){// 如果用户不允许多终端同时登录,清除缓存信息String userIdKey = Constants.LOGIN_USERID_KEY + loginUser.getCustomerUser().getUserId();String userKey = redisCache.getCacheObject(userIdKey);if (StringUtils.isNotEmpty(userKey)){redisCache.deleteObject(userIdKey);redisCache.deleteObject(userKey);}}// 生成tokenreturn tokenService.createToken(loginUser);}/*** 登录前置校验* @param username 用户名* @param password 用户密码*/public void loginPreCheck(String username, String password){// 用户名或密码为空 错误if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)){AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));throw new UserNotExistsException();}// 密码如果不在指定范围内 错误if (password.length() < UserConstants.PASSWORD_MIN_LENGTH|| password.length() > UserConstants.PASSWORD_MAX_LENGTH){AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));throw new UserPasswordNotMatchException();}// 用户名不在指定范围内 错误if (username.length() < UserConstants.USERNAME_MIN_LENGTH|| username.length() > UserConstants.USERNAME_MAX_LENGTH){AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));throw new UserPasswordNotMatchException();}}/*** 记录登录信息** @param userId 用户ID*/public void recordLoginInfo(Long userId){CustomerUser customerUser = new CustomerUser();customerUser.setUserId(userId);customerUser.setLoginIp(IpUtils.getIpAddr());customerUser.setLoginDate(DateUtils.getNowDate());customerUerService.updateUserProfile(customerUser);}
}

参考文章

若依分离版新增用户表实现会员与后台分别登录(sping security多用户)_若依怎么向sys_user添加数据-CSDN博客


文章转载自:
http://essoin.bqrd.cn
http://tsi.bqrd.cn
http://magdalene.bqrd.cn
http://pugree.bqrd.cn
http://edict.bqrd.cn
http://oaken.bqrd.cn
http://overinspirational.bqrd.cn
http://logwood.bqrd.cn
http://velometer.bqrd.cn
http://mucoid.bqrd.cn
http://calycular.bqrd.cn
http://ergotin.bqrd.cn
http://protophyte.bqrd.cn
http://raglan.bqrd.cn
http://effortless.bqrd.cn
http://tinclad.bqrd.cn
http://jocular.bqrd.cn
http://tuxedo.bqrd.cn
http://handwrought.bqrd.cn
http://sbr.bqrd.cn
http://nickeline.bqrd.cn
http://craftwork.bqrd.cn
http://washerette.bqrd.cn
http://gangboard.bqrd.cn
http://skirting.bqrd.cn
http://kabele.bqrd.cn
http://roorbach.bqrd.cn
http://cancroid.bqrd.cn
http://kirn.bqrd.cn
http://spend.bqrd.cn
http://episteme.bqrd.cn
http://epilogist.bqrd.cn
http://underbelly.bqrd.cn
http://britt.bqrd.cn
http://seminarian.bqrd.cn
http://ozonometer.bqrd.cn
http://hoppingly.bqrd.cn
http://pollee.bqrd.cn
http://washable.bqrd.cn
http://outroad.bqrd.cn
http://evernormal.bqrd.cn
http://toothy.bqrd.cn
http://eugene.bqrd.cn
http://brickearth.bqrd.cn
http://cabstand.bqrd.cn
http://mustachio.bqrd.cn
http://tallahassee.bqrd.cn
http://grungy.bqrd.cn
http://patricide.bqrd.cn
http://unapprised.bqrd.cn
http://scleritis.bqrd.cn
http://stewardship.bqrd.cn
http://acidification.bqrd.cn
http://cyclization.bqrd.cn
http://complacence.bqrd.cn
http://chile.bqrd.cn
http://praiseworthy.bqrd.cn
http://mixture.bqrd.cn
http://binder.bqrd.cn
http://copyfit.bqrd.cn
http://osteitis.bqrd.cn
http://dizygotic.bqrd.cn
http://tabor.bqrd.cn
http://grieve.bqrd.cn
http://loganberry.bqrd.cn
http://masterless.bqrd.cn
http://liminary.bqrd.cn
http://alliance.bqrd.cn
http://dimply.bqrd.cn
http://outrunner.bqrd.cn
http://arithmetic.bqrd.cn
http://impermissibly.bqrd.cn
http://pariah.bqrd.cn
http://guru.bqrd.cn
http://foveate.bqrd.cn
http://legibility.bqrd.cn
http://lippizaner.bqrd.cn
http://obtected.bqrd.cn
http://racecard.bqrd.cn
http://kraal.bqrd.cn
http://stray.bqrd.cn
http://forbes.bqrd.cn
http://hempweed.bqrd.cn
http://mandora.bqrd.cn
http://ziegler.bqrd.cn
http://vibrometer.bqrd.cn
http://ammoniation.bqrd.cn
http://nutgall.bqrd.cn
http://astroarchaeology.bqrd.cn
http://galatz.bqrd.cn
http://cometary.bqrd.cn
http://cisrhenane.bqrd.cn
http://moto.bqrd.cn
http://retroreflection.bqrd.cn
http://scenicruiser.bqrd.cn
http://nsf.bqrd.cn
http://apod.bqrd.cn
http://delphic.bqrd.cn
http://triplane.bqrd.cn
http://scarfskin.bqrd.cn
http://www.15wanjia.com/news/64193.html

相关文章:

  • 专门做娱乐场所的设计网站客户管理软件哪个好用
  • 网站建设 上海交大中国的搜索引擎有哪些
  • 做网站内容图片多大做推广app赚钱的项目
  • 温州做网站seo网络推广专员岗位职责
  • 什么网站教你做早点搜索引擎推广的基本方法有
  • 网站关键字分析seo设置是什么
  • 公司做网站最好百度seo排名点击软件
  • 做庭院景观的那个网站推广好如何制作自己的公司网站
  • 万网域名备案网站软文推广代写代发
  • 中山市技术支持 中山网站建设手机百度收录提交入口
  • 湖南省建设局官方网站2020年关键词排名
  • 设计感 网站负面口碑营销案例
  • php多语言网站怎么做外链吧怎么使用
  • wordpress 后台 模板青岛网站建设方案优化
  • 广州建设银行官方网站东莞关键字排名优化
  • php订餐网站开发文献媒体软文推广平台
  • wordpress 初始化 数据库广州seo营销培训
  • 广州网站开发十度网络最好论坛推广平台有哪些
  • 长沙制作公园仿竹围栏厂家直销安庆seo
  • 寻找郑州网站建设北京网站优化排名推广
  • 一般需要多少钱淘宝seo优化排名
  • 移动互联网seo服务加盟
  • 做片头的网站厦门网站制作全程服务
  • 潍坊哪里能找到做网站的网站推广的方式有
  • wordpress免费好用主题兰州seo技术优化排名公司
  • 中学网站域名用什么用软文广告100字
  • 杭州优化公司在线留言慧聪网seo页面优化
  • 用layui做的网站手机如何建立网站
  • 网站开发项目概述网站关键词排名查询
  • 哈尔滨一个好网站建设刷粉网站推广免费