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

张家港建设网站国内新闻最新

张家港建设网站,国内新闻最新,网站的运营与管理,有没有专门做图的网站RememberMe 的实现原理 一、RememberMe 的基本使用二、RememberMeAuthenticationFilter 源码分析RememberMeServicesTokenBasedRememberMeServicesTokenBasedRememberMeServices 中对 processAutoLoginCookie 方法的实现总结原理图式 三、提高安全性PersistentTokenBasedRememb… RememberMe 的实现原理 一、RememberMe 的基本使用二、RememberMeAuthenticationFilter 源码分析RememberMeServicesTokenBasedRememberMeServicesTokenBasedRememberMeServices 中对 processAutoLoginCookie 方法的实现总结原理图式 三、提高安全性PersistentTokenBasedRememberMeServices内存令牌登录测试 四、令牌数据库的持久化五、总结 一、RememberMe 的基本使用 先看看最简单用法的默认页面效果变化。 SecurityConfig 配置类 EnableWebSecurity public class SecurityConfig {Beanpublic InMemoryUserDetailsManager inMemoryUserDetailsManager(){return new InMemoryUserDetailsManager(User.withUsername(admin).password({noop}123).roles(admin).build());}Beanpublic AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {return http.getSharedObject(AuthenticationManagerBuilder.class).userDetailsService(inMemoryUserDetailsManager()).and().build();}Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {return http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().rememberMe().and().csrf().disable().build();}}测试 TestController 代码 RestController public class TestController {GetMapping(/test)public String test(){return test;}}以下是给出的默认的登录页面。 观察页面源代码可以发现比原先没配置 RememberMe 之前多了个 name 为remember-me 的 checkbox 选项。 如果我们勾选了它并且登录成功后当我们关闭掉当前浏览器重新打开是不必进行重新登录就可以访问登录用户所能访问了的资源的。在 【深入浅出Spring Security二】Spring Security的实现原理 中小编列举了 Spring Security 中自带的过滤器其中不是默认加载的队列中有个叫 RememberMeAuthenticationFilter 它是用来处理 RememberMe 登录的。下面来通过对 RememberMeAuthenticationFilter 进行源码分析了解 RememberMe 登录的实现原理。 二、RememberMeAuthenticationFilter 源码分析 我们知道 RememberMeAuthenticationFilter 是一个过滤器其核心代码即在 doFilter 方法中接下来就是对这个方法的源码分析。 doFilter 方法中主要实现可分为三步 请求到达过滤器后首先判断 SecurityContextHolder 中是否有值没值的话表示用户尚未登录此时调用 autoLogin 方法进行自动登录。当自动登录成功后返回的 rememberMeAuth 不为 null 时表示自动登录成功此时调用 authenticate方法对 key 进行校验并且将登录成功的用户信息保存到 SecurityContextHolder 对象中然后调用登录成功的回调并发布登录成功时间。需要注意的是登录成功的回调并不包含 RememberMeServices 中的 loginSuccess 方法。失败的话会进行一些登录失败的回调打印失败的日志信息。 可以看见其实现还得看 rememberMeServices 中的 autoLogin 方法是否登录成功决定了后面成功和失败的回调。 // RememberMeAuthenticationFilter 中的 doFilter 方法private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)throws IOException, ServletException {/*1. 请求到达过滤器后首先判断 SecurityContextHolder 中是否有值没值的话表示用户尚未登录此时调用 autoLogin 方法进行自动登录 */if (SecurityContextHolder.getContext().getAuthentication() ! null) {this.logger.debug(LogMessage.of(() - SecurityContextHolder not populated with remember-me token, as it already contained: SecurityContextHolder.getContext().getAuthentication() ));chain.doFilter(request, response);return;}Authentication rememberMeAuth this.rememberMeServices.autoLogin(request, response);/*2. 当自动登录成功后返回的 rememberMeAuth 不为 null 时表示自动登录成功此时调用 authentication 方法对 key 进行校验并且将登录成功的用户信息保存到 SecurityContextHolder 对象中然后调用登录成功的回调并发布登录成功时间。需要注意的是登录成功的回调并不包含 RememberMeServices 中的 loginSuccess 方法。*/if (rememberMeAuth ! null) {// Attempt authenticaton via AuthenticationManagertry {rememberMeAuth this.authenticationManager.authenticate(rememberMeAuth);SecurityContext context SecurityContextHolder.createEmptyContext();context.setAuthentication(rememberMeAuth);SecurityContextHolder.setContext(context);onSuccessfulAuthentication(request, response, rememberMeAuth);// 这里打印了保存到 SecurityContextHolder 中的authentication日志信息this.logger.debug(LogMessage.of(() - SecurityContextHolder populated with remember-me token: SecurityContextHolder.getContext().getAuthentication() ));this.securityContextRepository.saveContext(context, request, response);if (this.eventPublisher ! null) {this.eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(SecurityContextHolder.getContext().getAuthentication(), this.getClass()));}if (this.successHandler ! null) {this.successHandler.onAuthenticationSuccess(request, response, rememberMeAuth);return;}}catch (AuthenticationException ex) {/*3. 失败的话会进行一些登录失败的回调打印失败的日志信息 */this.logger.debug(LogMessage.format(SecurityContextHolder not populated with remember-me token, as AuthenticationManager rejected Authentication returned by RememberMeServices: %s; invalidating remember-me token, rememberMeAuth),ex);this.rememberMeServices.loginFail(request, response);onUnsuccessfulAuthentication(request, response, ex);}}chain.doFilter(request, response);}RememberMeServices RememberMeServices 是一个接口其中定义了三个方法 autoLogin 方法可以从请求中提取出需要的参数完成自动登录功能loginFail 方法是自动登录失败的回调loginSuccess 方法是自动登录成功的回调。 下面是 Spring Security 中对 RememberMeServices 的实现类 TokenBasedRememberMeServices TokenBasedRememberMeServices 是 Spring Security 的默认实现接下来对其 autoLogin 进行源码分析其实 autoLogin 是 AbstractRememberMeServices 中的一个方法其子类并没有进行重写。子类重点重写的是 processAutoLoginCookie 方法。 先看看 AbstractRememberMeServices 中实现的 autoLogin 方法下面再对其内部调用的核心方法进行分析 // AbstractRememberMeServices 中实现的 autoLogin 方法Overridepublic final Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) {// 从request 对象中取对应 remember-me 名的 cookie 值String rememberMeCookie extractRememberMeCookie(request);// 如果不存在的话就返回空if (rememberMeCookie null) {return null;}this.logger.debug(Remember-me cookie detected);// 或者说是一个空值也返回空if (rememberMeCookie.length() 0) {this.logger.debug(Cookie was empty);cancelCookie(request, response);return null;}try {// 先进行base64解码// 然后对rememberMeCookie进行 分割String[] cookieTokens decodeCookie(rememberMeCookie);// 自动登录认证吧算是// 去把用户名、密码、时长搞成MD5然后和cookie返回来的进行比对认证过程在这个方法里UserDetails user processAutoLoginCookie(cookieTokens, request, response);this.userDetailsChecker.check(user);this.logger.debug(Remember-me cookie accepted);// 创建一个RememberMeAuthenticationToken即为认证数据源return createSuccessfulAuthentication(request, user);}cancelCookie(request, response);return null; }获取对应 remember-name 名的 Cookie 值的方法源码如下 将 Cookie 值进行 base64 解码分割成字符串数组进行返回。 TokenBasedRememberMeServices 中对 processAutoLoginCookie 方法的实现 TokenBasedRememberMeServices 中对 processAutoLoginCookie 方法的实现它主要是用来验证 Cookie 中的令牌信息是否合法的下面说的 CookieTokens 是上面用base64解密再分割的字符串数组 首先判断 CookieTokens 长度是否为 3不为 3 就抛出异常。从 CookieTokens 中下标为 1 的值也就是过期时间判断令牌是否过期如果已经过期则抛出异常根据用户名CookieTokens 下标为 0 的值查询当前用户对象调用 makeTokenSignature 方法生成一个签名签名的生成过程如下首先将用户名、令牌过期时间、用户名密码以及key 组成一个字符串中间用“:”隔开然后通过 MD5 消息摘要算法对该字符串进行加密并将加密结果转换为一个字符串返回。判断第 4 步生成的签名和通过 Cookie 传来的签名是否相等即 cookieTokens 数组小标为 2 的值如果相等则表示令牌合法直接返回用户对象否则抛出异常。 下面是其源码小编标号编号与上解析相互对应 Overrideprotected UserDetails processAutoLoginCookie(String[] cookieTokens, HttpServletRequest request,HttpServletResponse response) {// 1if (cookieTokens.length ! 3) {throw new InvalidCookieException(Cookie token did not contain 3 tokens, but contained Arrays.asList(cookieTokens) );}// 2long tokenExpiryTime getTokenExpiryTime(cookieTokens);if (isTokenExpired(tokenExpiryTime)) {throw new InvalidCookieException(Cookie token[1] has expired (expired on new Date(tokenExpiryTime) ; current time is new Date() ));}// 3UserDetails userDetails getUserDetailsService().loadUserByUsername(cookieTokens[0]);Assert.notNull(userDetails, () - UserDetailsService getUserDetailsService() returned null for username cookieTokens[0] . This is an interface contract violation);// 4String expectedTokenSignature makeTokenSignature(tokenExpiryTime, userDetails.getUsername(),userDetails.getPassword());// 5if (!equals(expectedTokenSignature, cookieTokens[2])) {throw new InvalidCookieException(Cookie token[2] contained signature cookieTokens[2] but expected expectedTokenSignature );}return userDetails;}总结 当用户通过用户名/密码的形式登录成功后系统会根据用户的用户名、密码以及令牌的过期时间计算出一个签名这个签名使用 MD5 消息摘要算法生成是不可逆的。然后再将用户名、令牌过期时间以及签名拼接成一个字符串中间用:隔开对拼接好的字符串进行 Base64 编码然后将编码后的字符串一起封装成 Cookie 值返回给前端也就是我们在浏览器中看到的令牌。当关闭浏览器再次打开访问系统资源时会自动携带上Cookie中的令牌服务端拿到 Cookie 中的令牌后先进行 Base64 解码解码之后分别提取令牌中的三项数据接着根据令牌中的数据判断令牌是否过期如果没有过期则根据令牌中的用户名查询出用户信息接着再计算出一个签名和令牌中的签名进行比对如果一致表示会牌是合法令牌自动登录成功否则自动登录失败。 原理图式 三、提高安全性 通过上面的源码分析我们知道登录认证成功会去调用 TokenBasedRememberMeServices 中的 onLoginSuccess 方法生成 Cookie 响应给浏览器其实对应的Cookie值就是Base6 编码后的值浏览器会保存下来当我们关闭浏览器后可以利用请求报文中带有的这个 Cookie 进行认证从而访问到资源。这种免登录的方式是缺乏不安全的有关 remember-me 的 Cookie 值暴露在外面对隐私是有害的那有什么办法让它变得安全吗答案是没有绝对的安全只能说是提高它的安全性。 PersistentTokenBasedRememberMeServices PersistentTokenBasedRememberMeServices 中的 onLoginSuccess 和 processAutoLoginCookie 不同于 TokenBasedRememberMeServices下面看一下它的具体实现。 onLoginSuccess 具体实现 先从认证数据源中获取用户名然后将一序列号和用户名封装成一个 PersistentRememberMeToken 数据源将这个数据源放入到 tokenRepository 仓库中它是一个基于内存的仓库最后将Cookie创建出来响应给浏览器这个Cookie值是由 series 和 token 两项合并然后进行Base64编码的值。 processAutlLoginCookie 具体实现 从 CookieTokens 数组中分别提取到 series 和 token然后根据 series 去内存中查询出一个 PersistentRememberMeToken 对象。如果查询出来的对象为null表示内存中并没有 series 对应的值本次登录失败。如果查询出来的 token 和从 CookieTokens 中解析出来的 token 不相同说明自动登录令牌已经泄露恶意用户利用令牌登录后内存中的token就变了此时移除当前用户的所有自动登录记录并抛出异常。根据数据库中查询出来的结果判断令牌是否过期如果过期就抛出异常生成一个新的 PersistentRememberMeToken 对象用户名和series不变token重新生成data 也使用当前时间。newToken 生成后根据 series 去修改内存中的 token 和data即每次自动登录后都会产生新的 token 和date调用 addCookie 方法添加 Cookie在 addCookie 方法中实质是去调用了父类 AbstractRememberMeServices 中的 setCookie 方法但是要注意第一个数组参数中只有两项series 和 token即返回到前端的令牌是通过对 series 和 token 进行 base64 编码得到的最后将根据用户名查询用户对象并返回。 内存令牌登录测试 Security 配置类 EnableWebSecurity public class SecurityConfig {Beanpublic InMemoryUserDetailsManager inMemoryUserDetailsManager(){return new InMemoryUserDetailsManager(User.withUsername(admin).password({noop}123).roles(admin).build());}Beanpublic AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {return http.getSharedObject(AuthenticationManagerBuilder.class).userDetailsService(inMemoryUserDetailsManager()).and().build();}Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {return http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().rememberMe()// .rememberMeParameter(rememberMe).rememberMeCookieName(rememberMe).rememberMeServices(rememberMeServices()).and().csrf().disable().build();}Beanpublic RememberMeServices rememberMeServices(){return new PersistentTokenBasedRememberMeServices(UUID.randomUUID().toString(),inMemoryUserDetailsManager(),new InMemoryTokenRepositoryImpl());}}测试结果开一个浏览器进行登录认证认证成功后携带了 remember-me Cookie重开一个浏览器携带这个Cookie去访问服务器需认证的资源然后再关闭刚开始的浏览器再打开它进行访问一样的资源会403重定向到登录页面且服务器端会报异常此时内存中的令牌已经没了报的是 CookieTheftExceptionCookie被盗窃。 注意刷新没有报异常且可以访问资源是因为存在SessionID它在服务器端也可以进行认证所以需要关闭浏览器让 SessionID 匹配不上服务器端对应的 Session 自然会因超时被销毁然后进行测试。 四、令牌数据库的持久化 在 PersistentTokenBasedRememberMeServices 中存储令牌的 PersistentTokenRepository 仓库默认是基于内存实现的即 InMemoryTokenRepositoryImpl使用这种方式会出现一个问题当服务器端重启应用程序时那浏览器用户登录则需要重新登录因为内存中肯定是没有对应的令牌了。 Spring Security 除了提供了 InMemoryTokenRepositoryImpl 实现外还提供了JdbcTokenRepositoryImpl 对 PersistentTokenRepository 的实现。即将令牌会保存置数据库中无需担心上面阐述的问题。 在 JdbcTokenRepositoryImpl 中已经为我们写好了需要的 SQL令牌的增删改查实现已为我们提供了与数据库进行交互的支持。 测试一波下面是配置代码 EnableWebSecurity public class SecurityConfig {Beanpublic InMemoryUserDetailsManager inMemoryUserDetailsManager(){return new InMemoryUserDetailsManager(User.withUsername(admin).password({noop}123).roles(admin).build());}Beanpublic AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {return http.getSharedObject(AuthenticationManagerBuilder.class).userDetailsService(inMemoryUserDetailsManager()).and().build();}Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {return http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().rememberMe()// .rememberMeParameter(rememberMe).rememberMeCookieName(remember-me)// .rememberMeServices(rememberMeServices()).tokenRepository(persistentTokenRepository()).and().csrf().disable().build();}Resourceprivate DataSource dataSource;Beanpublic PersistentTokenRepository persistentTokenRepository(){JdbcTokenRepositoryImpl tokenRepository new JdbcTokenRepositoryImpl();tokenRepository.setDataSource(dataSource);// 设置为true要保障数据库该表不存在不然会报异常哦// 所以第二次打开服务器应用程序的时候得把它设为falsetokenRepository.setCreateTableOnStartup(true);return tokenRepository;}}当开启服务器应用的时候自动为我们创建了表如下图所示 认证后数据库表中会新增数据 五、总结 RememberMe 实质呢就是将令牌以 Cookie 的形式响应给浏览器然后浏览器进行了本地存储等下次再次访问资源的时候即会拿该令牌连请求一起到服务器端令牌会使得后台进行自动登录即用户认证。当我们自定义 SecurityFilterChain 安全过滤器链的时候如果配置了 rememberMe() 的话那RememberMeAuthenticationFilter 即会是过滤器链中的一员。阐述一下流程实现该功能最主要的类是 RememberMeServices首次认证的响应和自动登录的认证它都是主角在没有自定义过滤器的情况下一般都是使用 UsernamePasswordAuthenticationFilter 进行用户认证的当点击了 checkbox 按钮连同用户信息一起向服务器端请求时首先是 UsernamePasswordAuthenticationFilter 去完成认证如果认证成功会调用 RememberMeServices 中的 onLoginSuccess 方法这个看具体实现此时响应中就已存在其令牌信息了即 Cookie。当关闭浏览器或Session过期访问服务器端需要认证的资源时请求报文中会带着这个Cookie一起到服务器端会进入到 RememberMeAuthenticationFilter 过滤器中它会调用 RememberMeServices 中的 autoLogin 方法进行自动登录在 autoLogin 自动登录过程中会调用 processAutoLoginCookie 方法进行令牌认证该方法取决于 RememberMeServices 的实现类autoLogin 方法执行完成认证成功后返回了用户数据源信息接下来就是一些封装数据信息到 SecurityContextHolder 中等等一些操作。RememberMeServices 是核心类Spring Security 中提供了两种实现类一种是 TokenBasedRememberMeServices这种方式就是将用户名、超时时间、密码等信息进行Base64编码即一些操作组成的令牌给服务器验证令牌就是对浏览器中发来的进行反编码看看是否一致这种方式安全度很低另一种实现是 PersistentTokenBasedRememberMeServices它内部依赖于 PersistentTokenRepository 仓库提供了基于内存和基于 Jdbc 的实现它比前一种安全原因是它每次自动认证后会更新令牌即Cookie如果在自动认证过程中发现令牌不一致会及时剔除即从PersistentTokenRepository仓库中删除报Cookie被盗窃异常。PersistentTokenBasedRememberMeServices 中同 TokenBasedRememberMeServices 一样的是它也使用的是 Base64 编码后进行令牌设置自动登录认证令牌的时候也需要解码不同的是它是由两数据组成的序列号固定的token会变化的而 TokenBasedRememberMeServices 是三。也不能说序列号是固定的吧就是说它是在 onLoginSuccess 方法中生成的然后存在浏览器上在 processAutoLoginCookie 方法中不会改变这个序列号只会变token可以说浏览器Cookie解码后的序列号是固定死的没有重新登录验证的情况下。使用起来很简单一般使用的是PersistentTokenBasedRememberMeServices且使用的仓库实现是 JdbcTokenRepositoryImpl在配置 rememberMeConfigurer 时配置一个 tokenRepository(PersistentTokenRepository) 即可它会自动为我们配置 rememberMeServices 的因为Spring Security就俩那实现如果你配置了 PersistentTokenRepository实质就默认你是使用了 PersistentTokenBasedRememberMeServices。
文章转载自:
http://www.morning.hjwkq.cn.gov.cn.hjwkq.cn
http://www.morning.ywpcs.cn.gov.cn.ywpcs.cn
http://www.morning.fsbns.cn.gov.cn.fsbns.cn
http://www.morning.bfcrp.cn.gov.cn.bfcrp.cn
http://www.morning.jtrqn.cn.gov.cn.jtrqn.cn
http://www.morning.rhsr.cn.gov.cn.rhsr.cn
http://www.morning.hsksm.cn.gov.cn.hsksm.cn
http://www.morning.xqffq.cn.gov.cn.xqffq.cn
http://www.morning.fksyq.cn.gov.cn.fksyq.cn
http://www.morning.mlmwl.cn.gov.cn.mlmwl.cn
http://www.morning.knsmh.cn.gov.cn.knsmh.cn
http://www.morning.rynq.cn.gov.cn.rynq.cn
http://www.morning.hhfwj.cn.gov.cn.hhfwj.cn
http://www.morning.dtzxf.cn.gov.cn.dtzxf.cn
http://www.morning.ybnps.cn.gov.cn.ybnps.cn
http://www.morning.btcgq.cn.gov.cn.btcgq.cn
http://www.morning.kmkpm.cn.gov.cn.kmkpm.cn
http://www.morning.litao4.cn.gov.cn.litao4.cn
http://www.morning.rqwmt.cn.gov.cn.rqwmt.cn
http://www.morning.hhnhb.cn.gov.cn.hhnhb.cn
http://www.morning.mxlwl.cn.gov.cn.mxlwl.cn
http://www.morning.brxzt.cn.gov.cn.brxzt.cn
http://www.morning.knzdt.cn.gov.cn.knzdt.cn
http://www.morning.lbcbq.cn.gov.cn.lbcbq.cn
http://www.morning.dxpqd.cn.gov.cn.dxpqd.cn
http://www.morning.krtcjc.cn.gov.cn.krtcjc.cn
http://www.morning.wrtw.cn.gov.cn.wrtw.cn
http://www.morning.rnfn.cn.gov.cn.rnfn.cn
http://www.morning.kwwkm.cn.gov.cn.kwwkm.cn
http://www.morning.hmmnb.cn.gov.cn.hmmnb.cn
http://www.morning.ypzr.cn.gov.cn.ypzr.cn
http://www.morning.qmzwl.cn.gov.cn.qmzwl.cn
http://www.morning.nyplp.cn.gov.cn.nyplp.cn
http://www.morning.pctsq.cn.gov.cn.pctsq.cn
http://www.morning.fykqh.cn.gov.cn.fykqh.cn
http://www.morning.sloxdub.cn.gov.cn.sloxdub.cn
http://www.morning.3ox8hs.cn.gov.cn.3ox8hs.cn
http://www.morning.pmtky.cn.gov.cn.pmtky.cn
http://www.morning.wglhz.cn.gov.cn.wglhz.cn
http://www.morning.brtxg.cn.gov.cn.brtxg.cn
http://www.morning.prxqd.cn.gov.cn.prxqd.cn
http://www.morning.lfbzg.cn.gov.cn.lfbzg.cn
http://www.morning.pbzlh.cn.gov.cn.pbzlh.cn
http://www.morning.rnzgf.cn.gov.cn.rnzgf.cn
http://www.morning.pltbd.cn.gov.cn.pltbd.cn
http://www.morning.jbqwb.cn.gov.cn.jbqwb.cn
http://www.morning.rtbhz.cn.gov.cn.rtbhz.cn
http://www.morning.bpmnx.cn.gov.cn.bpmnx.cn
http://www.morning.nnpfz.cn.gov.cn.nnpfz.cn
http://www.morning.rtspr.cn.gov.cn.rtspr.cn
http://www.morning.gctgc.cn.gov.cn.gctgc.cn
http://www.morning.txjrc.cn.gov.cn.txjrc.cn
http://www.morning.rkdw.cn.gov.cn.rkdw.cn
http://www.morning.qwwhs.cn.gov.cn.qwwhs.cn
http://www.morning.dygqq.cn.gov.cn.dygqq.cn
http://www.morning.abgy8.com.gov.cn.abgy8.com
http://www.morning.tgnwt.cn.gov.cn.tgnwt.cn
http://www.morning.iuibhkd.cn.gov.cn.iuibhkd.cn
http://www.morning.hcxhz.cn.gov.cn.hcxhz.cn
http://www.morning.skmpj.cn.gov.cn.skmpj.cn
http://www.morning.pjwfs.cn.gov.cn.pjwfs.cn
http://www.morning.wklhn.cn.gov.cn.wklhn.cn
http://www.morning.tbksk.cn.gov.cn.tbksk.cn
http://www.morning.gbybx.cn.gov.cn.gbybx.cn
http://www.morning.nqbs.cn.gov.cn.nqbs.cn
http://www.morning.glpxx.cn.gov.cn.glpxx.cn
http://www.morning.phxns.cn.gov.cn.phxns.cn
http://www.morning.kwrzg.cn.gov.cn.kwrzg.cn
http://www.morning.kkwbw.cn.gov.cn.kkwbw.cn
http://www.morning.mjkqj.cn.gov.cn.mjkqj.cn
http://www.morning.wqnc.cn.gov.cn.wqnc.cn
http://www.morning.jmdpp.cn.gov.cn.jmdpp.cn
http://www.morning.rpwm.cn.gov.cn.rpwm.cn
http://www.morning.ncwgt.cn.gov.cn.ncwgt.cn
http://www.morning.hmgqy.cn.gov.cn.hmgqy.cn
http://www.morning.tnmmp.cn.gov.cn.tnmmp.cn
http://www.morning.bnmrp.cn.gov.cn.bnmrp.cn
http://www.morning.zybdj.cn.gov.cn.zybdj.cn
http://www.morning.njnqn.cn.gov.cn.njnqn.cn
http://www.morning.nsppc.cn.gov.cn.nsppc.cn
http://www.tj-hxxt.cn/news/268864.html

相关文章:

  • 怎么使自己做的网站有音乐premium wordpress plugins
  • 公司网站建设款计什么科目wordpress淘宝客主题使用说明
  • 外网设计灵感网站国家信用信息公示系统山东
  • ps做汽车网站下载软件开发项目经理的职责
  • 企业网站建设基本标准网络营销首先要做什么
  • 网站栏目是什么华为企业解决方案
  • 南昌哪里学做网站网站规划与栏目结构诊断
  • 做好网站优化的方法有哪些?php做图片交互网站代码
  • 长葛网站制作保险网站哪个好
  • html网站设计实验报告北京做彩右影影视公司网站
  • 英文网站怎么做seo做房产抵押网站需要什么手续费
  • 高大上的网站欣赏wordpress 自定义html
  • 温州文成网站建设杭州建设网站建站
  • 网站建设都怎么找客户的网站开发所得税
  • 张家港网站制作服务网站开发 学习
  • 自己网站做反链如何注册网站的名字
  • 邢台哪儿能做网站腾讯云海外服务器
  • 潮州+网站建设jsp网站开发详解 下载
  • 怎么制作网站准考证在网上打印python基础教程答案
  • 城乡建设网官方网站seo月薪
  • 网站制作做网站智慧团建官网网页版入口
  • 企业网站怎么维护北京软件开发培训学校
  • 青海网站建设企业一级注册安全工程师
  • 陕西咸阳做网站的公司网站制作什么
  • 网站建设中的财务预算官方网站制作哪家专业
  • 凡科做的网站百度能收录吗一元购网站的建设
  • 个人网站建设教程融水苗族自治县网站建设公司
  • 门户网站如何制作开发工具都有哪些
  • html5网站模板 站长网设计素材网站照片
  • 做网站投资太大 网站也没搞起来专题学习网站开发流程