专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

SpringSecurity如何验证accesstoken

  在客户端获取到令牌后,访问资源时,可以设置如下请求头或者请求参数中加上accesstoken。Authorization:Beareraccesstoken
  在前两篇《auth2生成token》和《token转jwt》中,我们已经知道accesstoken产生的大体流程,并且知道如何自定义token的格式,其中,授权服务器配置中的AuthorizationServerEndpointsConfigurer可谓极为重要;而关于accesstoken的验证流程,我们就从对应的资源服务器的配置入手。1资源服务器配置
  与生成accesstoken有固定接口oauthtoken不同,我们肯定不能通过业务资源的接口地址去找到验证token源码的入口。SpringSecurity原理是责任链模式,绝大数功能都是过滤器实现的,这里也不例外。资源服务器的配置如下:
  这里重点关注一下ResourceServerSecurityConfigurer。ConfigurationEnableResourceServerpublicclassResourceServerConfigextendsResourceServerConfigurerAdapter{Overridepublicvoidconfigure(ResourceServerSecurityConfigurerresources)throwsException{resources。resourceId(message)设置资源id。tokenStore(newJwtTokenStore(jwtAccessTokenConverter()))。tokenServices(newRemoteTokenServices())。tokenExtractor(newBearerTokenExtractor());}Overridepublicvoidconfigure(HttpSecurityhttp)throwsException{super。configure(http);}}2ResourceServerSecurityConfigurer
  在ResourceServerSecurityConfigurer中我们看到鉴权所需要的两个重要元素,Filter和AuthenticationManager。看到下面的代码,一些比较敏感的小伙伴可能会推测,所谓的accesstoken验证应该就是用这里配置的Filter和AuthenticationManager进行鉴权了。publicfinalclassResourceServerSecurityConfigurerextendsSecurityConfigurerAdapterDefaultSecurityFilterChain,HttpSecurity{。。。。。。privateOAuth2AuthenticationProcessingFilterresourcesServerFilter;privateAuthenticationManagerauthenticationManager;。。。。。。Overridepublicvoidconfigure(HttpSecurityhttp)throwsException{AuthenticationManageroauthAuthenticationManageroauthAuthenticationManager(http);N指定过滤器resourcesServerFilternewOAuth2AuthenticationProcessingFilter();resourcesServerFilter。setAuthenticationEntryPoint(authenticationEntryPoint);N设置AuthenticationManagerresourcesServerFilter。setAuthenticationManager(oauthAuthenticationManager);if(eventPublisher!null){resourcesServerFilter。setAuthenticationEventPublisher(eventPublisher);}if(tokenExtractor!null){resourcesServerFilter。setTokenExtractor(tokenExtractor);}resourcesServerFilterpostProcess(resourcesServerFilter);resourcesServerFilter。setStateless(stateless);formatter:offhttp。authorizeRequests()。expressionHandler(expressionHandler)。and()N将过滤器放到过滤器链中。addFilterBefore(resourcesServerFilter,AbstractPreAuthenticatedProcessingFilter。class)。exceptionHandling()。accessDeniedHandler(accessDeniedHandler)。authenticationEntryPoint(authenticationEntryPoint);formatter:on}privateAuthenticationManageroauthAuthenticationManager(HttpSecurityhttp){OAuth2AuthenticationManageroauthAuthenticationManagernewOAuth2AuthenticationManager();if(this。authenticationManager!null){如果自己配置了authenticationManagerif(authenticationManagerinstanceofOAuth2AuthenticationManager){oauthAuthenticationManager(OAuth2AuthenticationManager)authenticationManager;}else{returnauthenticationManager;}}oauthAuthenticationManager。setResourceId(resourceId);oauthAuthenticationManager。setTokenServices(resourceTokenServices(http));oauthAuthenticationManager。setClientDetailsService(clientDetails());returnoauthAuthenticationManager;}。。。。。。}
  通过上面的代码。addFilterBefore(resourcesServerFilter,AbstractPreAuthenticatedProcessingFilter。class)我们可以知道,用于处理令牌验证的过滤器应该就是OAuth2AuthenticationProcessingFilter了,并且默认AuthenticationManager是OAuth2AuthenticationManager。3OAuth2AuthenticationProcessingFilter
  过滤器肯定是要看doFilter了,核心逻辑如下:从request中提取出accesstoken,并构建authentication对象;设置authentication对象的details(tokentype、tokenvalue、sessionId、remoteAddress等,来源于request);利用authentication对象进行鉴权。鉴权成功对象放到SecurityContext中publicclassOAuth2AuthenticationProcessingFilterimplementsFilter,InitializingBean{privateTokenExtractortokenExtractornewBearerTokenExtractor();。。。。。。publicvoidsetAuthenticationManager(AuthenticationManagerauthenticationManager){this。authenticationManagerauthenticationManager;}publicvoidsetTokenExtractor(TokenExtractortokenExtractor){this。tokenExtractortokenExtractor;}。。。。。。publicvoiddoFilter(ServletRequestreq,ServletResponseres,FilterChainchain)throwsIOException,ServletException{booleandebuglogger。isDebugEnabled();HttpServletRequestrequest(HttpServletRequest)req;HttpServletResponseresponse(HttpServletResponse)res;try{N从request中提取accesstokenAuthenticationauthenticationthis。tokenExtractor。extract(request);if(authenticationnull){if(this。statelessthis。isAuthenticated()){if(debug){logger。debug(Clearingsecuritycontext。);}SecurityContextHolder。clearContext();}if(debug){logger。debug(Notokeninrequest,willcontinuechain。);}}else{N把accesstoken放到request属性中{OAuth2AuthenticationDetails。ACCESSTOKENVALUE:accesstoken}request。setAttribute(OAuth2AuthenticationDetails。ACCESSTOKENVALUE,authentication。getPrincipal());if(authenticationinstanceofAbstractAuthenticationToken){AbstractAuthenticationTokenneedsDetails(AbstractAuthenticationToken)authentication;request中的remoteAddress、sessionId、tokenValue、tokenType等信息放到details中needsDetails。setDetails(this。authenticationDetailsSource。buildDetails(request));}N鉴权AuthenticationauthResultthis。authenticationManager。authenticate(authentication);if(debug){logger。debug(Authenticationsuccess:authResult);}this。eventPublisher。publishAuthenticationSuccess(authResult);N设置安全上下文SecurityContextHolder。getContext()。setAuthentication(authResult);}}catch(OAuth2Exceptione){SecurityContextHolder。clearContext();if(debug){logger。debug(Authenticationrequestfailed:e);}this。eventPublisher。publishAuthenticationFailure(newBadCredentialsException(e。getMessage(),e),newPreAuthenticatedAuthenticationToken(accesstoken,NA));this。authenticationEntryPoint。commence(request,response,newInsufficientAuthenticationException(e。getMessage(),e));return;}chain。doFilter(request,response);}。。。。。。}
  关于BearerTokenExtractor,作用就是从request的请求头或者请求参数中提取accesstoken,并设置tokenType(例如bearer类型),逻辑相对简单,这里就不展开了。当然我们也可以定义自己的token提取器,只要在配置资源服务器时设置给ResourceServerSecurityConfigurer对象即可。4OAuth2AuthenticationManager
  AuthenticationManager的作用就是鉴权,这里的逻辑也很简单,就是验证token是否是真的由授权服务器产生,如果是,继续校验resourceId和scope。资源服务器默认的resourceId在ResourceServerSecurityConfigurer类中,是oauth2resource。
  如果令牌对应的resourceIds是空的,就不校验resourceId了,换种说法就是:如果我们数据库接入端表中没配置resourceId,就拥有所有资源服务器的访问权限,总感觉不爽。publicclassOAuth2AuthenticationManagerimplementsAuthenticationManager,InitializingBean{privateResourceServerTokenServicestokenServices;。。。。。。publicAuthenticationauthenticate(Authenticationauthentication)throwsAuthenticationException{if(authenticationnull){thrownewInvalidTokenException(Invalidtoken(tokennotfound));}N提取accesstokenStringtoken(String)authentication。getPrincipal();N验证accesstoken是否真的由授权服务器产生OAuth2AuthenticationauthtokenServices。loadAuthentication(token);if(authnull){thrownewInvalidTokenException(Invalidtoken:token);}CollectionStringresourceIdsauth。getOAuth2Request()。getResourceIds();N校验该令牌是否拥有访问资源服务器的权限if(resourceId!nullresourceIds!null!resourceIds。isEmpty()!resourceIds。contains(resourceId)){thrownewOAuth2AccessDeniedException(Invalidtokendoesnotcontainresourceid(resourceId));}N校验令牌和client的scope是否相符checkClientDetails(auth);if(authentication。getDetails()instanceofOAuth2AuthenticationDetails){OAuth2AuthenticationDetailsdetails(OAuth2AuthenticationDetails)authentication。getDetails();Guardagainstacachedcopyofthesamedetailsif(!details。equals(auth。getDetails())){Preservetheauthenticationdetailsfromtheoneloadedbytokenservicesdetails。setDecodedDetails(auth。getDetails());}}auth。setDetails(authentication。getDetails());auth。setAuthenticated(true);returnauth;}clientDetailsService可能为null,后面我们单独说明。privatevoidcheckClientDetails(OAuth2Authenticationauth){if(clientDetailsService!null){N进入这里说明要么我们自己设置了clientDetailsService,要么资源服务与授权服务是同一个服务ClientDetailsclient;try{clientclientDetailsService。loadClientByClientId(auth。getOAuth2Request()。getClientId());}catch(ClientRegistrationExceptione){thrownewOAuth2AccessDeniedException(Invalidtokencontainsinvalidclientid);}数据库查询到的客户端配置的scopeSetStringallowedclient。getScope();N校验令牌的scopefor(Stringscope:auth。getOAuth2Request()。getScope()){if(!allowed。contains(scope)){thrownewOAuth2AccessDeniedException(Invalidtokencontainsdisallowedscope(scope)forthisclient);}}}}}
  接下来我们继续探索tokenServices。loadAuthentication(token);方法都做了什么。5ResourceServerTokenServices
  ResourceServerTokenServices的默认实现是DefaultTokenServices,这段代码可以在ResourceServerSecurityConfigurer中看到,当然,如果我们配置了resourceTokenServices,在if中则会直接返回配置的实现。publicfinalclassResourceServerSecurityConfigurerextendsSecurityConfigurerAdapterDefaultSecurityFilterChain,HttpSecurity{。。。。。。privateResourceServerTokenServicestokenServices(HttpSecurityhttp){if(resourceTokenServices!null){returnresourceTokenServices;}DefaultTokenServicestokenServicesnewDefaultTokenServices();tokenServices。setTokenStore(tokenStore());tokenServices。setSupportRefreshToken(true);tokenServices。setClientDetailsService(clientDetails());this。resourceTokenServicestokenServices;returntokenServices;}privateClientDetailsServiceclientDetails(){获取授权服务设置的ClientDetailsServicereturngetBuilder()。getSharedObject(ClientDetailsService。class);}。。。。。。}
  Security为我们提供了两个ResourceServerTokenServices子类。
  5。1DefaultTokenServices
  通过tokenStore可以推测出,这个必须要和授权服务器能够访问相同的存储才行。(JwtTokenStore比较特殊,它并没有存储token,因为验证jwt只需要对称密钥或者公钥就可以,感兴趣的小伙伴可以看JwtTokenStore的源码)publicOAuth2AuthenticationloadAuthentication(StringaccessTokenValue)throwsAuthenticationException,InvalidTokenException{N从存储中读取accesstoken,这里JwtTokenStore实现的比较特殊,是返回接收到的jwtN显然这要求授权服务器和资源服务器能否访问相同的存储,例如DB或者redisOAuth2AccessTokenaccessTokenthis。tokenStore。readAccessToken(accessTokenValue);if(accessTokennull){thrownewInvalidTokenException(Invalidaccesstoken:accessTokenValue);}elseif(accessToken。isExpired()){令牌过期处理this。tokenStore。removeAccessToken(accessToken);thrownewInvalidTokenException(Accesstokenexpired:accessTokenValue);}else{N验证token,如果是JwtTokenStore,验证jwt签名OAuth2Authenticationresultthis。tokenStore。readAuthentication(accessToken);if(resultnull){thrownewInvalidTokenException(Invalidaccesstoken:accessTokenValue);}else{这里如果我们自己没有配置clientDetailsService,默认共享授权服务的,可能是nullif(this。clientDetailsService!null){StringclientIdresult。getOAuth2Request()。getClientId();try{this。clientDetailsService。loadClientByClientId(clientId);}catch(ClientRegistrationExceptionvar6){thrownewInvalidTokenException(Clientnotvalid:clientId,var6);}}returnresult;}}}
  这里说明一下clientDetailsService,上面我们提到OAuth2AuthenticationManager和DefaultTokenServices中的this。clientDetailsService都可能是null的问题。这是因为他们的取值都是ResourceServerSecurityConfigurer中的如下方法,getSharedObject获取的是授权服务配置的ClientDetailsService。当授权服务与资源服务不是同一个服务的时候,getSharedObject就会取不到值。privateClientDetailsServiceclientDetails(){获取授权服务设置的ClientDetailsServicereturngetBuilder()。getSharedObject(ClientDetailsService。class);}
  在上面分析令牌生成时,授权服务只是提到了AuthorizationServerEndpointsConfigurer的配置,这里我们补充一下另外两个配置。ConfigurationEnableAuthorizationServerpublicclassAuthorizationServerConfigextendsAuthorizationServerConfigurerAdapter{ResourceprivateDataSourcedataSource;对auth2提供的接口做访问规则配置和添加自定义过滤器Overridepublicvoidconfigure(AuthorizationServerSecurityConfigurersecurity)throwsException{security允许表单认证,对于接口oauthtoken,如果开启此配置,并且url中有clientid和clientsecret会触发ClientCredentialsTokenEndpointFilter用于校验客户端是否有权限。allowFormAuthenticationForClients()设置接口oauthchecktoken访问权限,默认denyAll(),资源服务器可以调用这个验证token,如果是jwt,资源服务器也可以自己通过密钥验证。checkTokenAccess(isAuthenticated())提供jwt的公钥接口oauthtokenkey。tokenKeyAccess(permitAll())N添加自定义的过滤器通过AbstractAuthenticationProcessingFilter断点的additionalFilter可以看到该过滤器再链中的位置。addTokenEndpointAuthenticationFilter(newMyFilterFive())。passwordEncoder();}接入端管理配置,对应的是oauthclientdetails表,实体是BaseClientDetailsOverridepublicvoidconfigure(ClientDetailsServiceConfigurerclients)throwsException{clients。inMemory()client1是客户端授权方式。withClient(client1)接入端id。secret(newBCryptPasswordEncoder()。encode(123456))接入端密钥。resourceIds(DEMORESOURCEID)资源id。authorizedGrantTypes(clientcredentials,refreshtoken)授权方式。scopes(select)访问域。authorities(client);权限clients。jdbc(dataSource);clients。withClientDetails(newJdbcClientDetailsService(dataSource));}SpringSecurityOAuth2默认提供以下端口oauthauthorize:授权端口oauthtoken:令牌端口oauthconfirmaccess:用户确认授权提交端口oautherror:授权服务错误信息端口oauthchecktoken:用于资源服务器访问的令牌解析端口oauthtokenkey:提供公有秘钥端口,如果使用的是JWT令牌的话pathMapping可以映射成其他地址Overridepublicvoidconfigure(AuthorizationServerEndpointsConfigurerendpoints)throwsException{endpoints。pathMapping(oauthtoken,clonelitoken)。allowedTokenEndpointRequestMethods(HttpMethod。GET,HttpMethod。POST)允许的请求方式tokenStore默认内存存储,重启服务token就会失效。tokenStore(newInMemoryTokenStore())。reuseRefreshTokens(true)。tokenEnhancer()。accessTokenConverter(jwtAccessTokenConverter())用于配置密码式的授权方式,如果不设置,密码模式请求token是,token为null,TokenEndpoint会提示不支持password授权模式,这里配置就是parentAuthenticationManager。authenticationManager(authenticationManager())。tokenGranter(newTokenGranter(){OverridepublicOAuth2AccessTokengrant(Strings,TokenRequesttokenRequest){returnnull;}});}}
  在上面AuthorizationServerSecurityConfigurer的配置中,可以看到我们设置了oauthchecktoken接口。checkTokenAccess(isAuthenticated()),即需要授权才能访问该接口。
  而权限的配置就在下面AuthorizationServerSecurityConfiguration的方法中,同时有包括setSharedObject的ClientDetailsService,因此授权服务和资源服务不是同一个服务,也就没有EnableAuthorizationServer注解,就不会执行setSharedObject的操作,这就是为什么getSharedObject(ClientDetailsService。class)可能是null的原因。ConfigurationOrder(0)ClientDetailsServiceConfiguration提供clientDetailsService的beanImport({ClientDetailsServiceConfiguration。class,AuthorizationServerEndpointsConfiguration。class})publicclassAuthorizationServerSecurityConfigurationextendsWebSecurityConfigurerAdapter{。。。。。。AutowiredprivateClientDetailsServiceclientDetailsService;。。。。。。Overrideprotectedvoidconfigure(HttpSecurityhttp)throwsException{AuthorizationServerSecurityConfigurerconfigurernewAuthorizationServerSecurityConfigurer();FrameworkEndpointHandlerMappinghandlerMappingendpoints。oauth2EndpointHandlerMapping();http。setSharedObject(FrameworkEndpointHandlerMapping。class,handlerMapping);configure(configurer);http。apply(configurer);StringtokenEndpointPathhandlerMapping。getServletPath(oauthtoken);StringtokenKeyPathhandlerMapping。getServletPath(oauthtokenkey);StringcheckTokenPathhandlerMapping。getServletPath(oauthchecktoken);if(!endpoints。getEndpointsConfigurer()。isUserDetailsServiceOverride()){UserDetailsServiceuserDetailsServicehttp。getSharedObject(UserDetailsService。class);endpoints。getEndpointsConfigurer()。userDetailsService(userDetailsService);}formatter:offhttp。authorizeRequests()。antMatchers(tokenEndpointPath)。fullyAuthenticated()设置接口的访问权限。antMatchers(tokenKeyPath)。access(configurer。getTokenKeyAccess())。antMatchers(checkTokenPath)。access(configurer。getCheckTokenAccess())。and()。requestMatchers()。antMatchers(tokenEndpointPath,tokenKeyPath,checkTokenPath)。and()。sessionManagement()。sessionCreationPolicy(SessionCreationPolicy。NEVER);formatter:onsetSharedObjectclientDetailsServicehttp。setSharedObject(ClientDetailsService。class,clientDetailsService);}。。。。。。}没有EnableAuthorizationServer注解,就不会执行AuthorizationServerSecurityConfiguration的方法Target(ElementType。TYPE)Retention(RetentionPolicy。RUNTIME)DocumentedImport({AuthorizationServerEndpointsConfiguration。class,AuthorizationServerSecurityConfiguration。class})publicinterfaceEnableAuthorizationServer{}5。2RemoteTokenServices
  见名知意,这个需要调用其他服务验证accesstoken,显然能提供这个服务的应该就是授权服务了。授权服务提供了CheckTokenEndpoint用于验证accesstoken的接口如下,而其底层实现也是resourceServerTokenServices。oauthchecktoken
  调用授权服务器的oauthchecktoken接口,我们上面提到需要授权服务器设置访问权限,这里用的是客户端模式。OverridepublicOAuth2AuthenticationloadAuthentication(StringaccessToken)throwsAuthenticationException,InvalidTokenException{MultiValueMapString,StringformDatanewLinkedMultiValueMapString,String();formData。add(tokenName,accessToken);HttpHeadersheadersnewHttpHeaders();N设置请求头,客户端凭证,访问授权服务器需要认证headers。set(Authorization,getAuthorizationHeader(clientId,clientSecret));N设置请求地址,并发送请求获取验证结果MapString,ObjectmappostForMap(checkTokenEndpointUrl,formData,headers);if(map。containsKey(error)){logger。debug(checktokenreturnederror:map。get(error));thrownewInvalidTokenException(accessToken);}Assert。state(map。containsKey(clientid),Clientidmustbepresentinresponsefromauthserver);N构造OAuth2Authentication对象returntokenConverter。extractAuthentication(map);}5。3LocalTokenServices(自定义)
  当然如果上面两种校验accesstoken的实现不能满足项目需求,也可以自定义自己的ResourceServerTokenServices实现类,重写验证accesstoken的逻辑。
  综上,整个令牌验证的流程就是ResourceServerSecurityConfigurer指定了OAuth2AuthenticationProcessingFilter过滤器,过滤器调用AuthenticationManager,AuthenticationManager又调用ResourceServerTokenServices实现令牌验证,其中具体实现我们可以通过资源服务配置进行修改。
  到这里,令牌验证通过,Authentication的信息就会放到线程变量SecurityContext中,然后过滤器就会放行请求。
  不过验证令牌后得到的权限信息还没有用到。publicinterfaceAuthenticationextendsPrincipal,Serializable{Collectionlt;?extendsGrantedAuthoritygetAuthorities();。。。。。。}
  这就要提到EnableGlobalMethodSecurity系列的注解了,我们以后再说。

37岁的萨顶顶跌落神坛,该怪假唱吗?2016年,本应该是萨顶顶创造事业新高潮的她。却被一次假唱风波打的措手不及。网友们无尽的嘲讽,就连同门姐妹金星也拿来吐槽。在大众眼里,她面对如此的舆论,实属活该。但是如今的她,又出好命的应采儿,和她生命中深爱的一个男人在娱乐圈中,应采儿和陈小春的婚姻,一直是大家羡慕的完美状态。两人性格互补的相处模式,也一直是被大家津津乐道。而在两人的婚姻中,应采儿一直是占据着主导地位,也带给了陈小春绝对的踏实和徐根宝痛心,34岁国脚被带走!前国手爆料体坛最高级别官员落马2023年中国足坛扫黑已经持续5个月时间,围绕足协内部的调查已经差不多结束了,合计9人被带走调查,包括李铁陈戌源于洪臣董铮杜兆才等大佬,63岁的杜兆才曾经计划在4月退休,开始享受生过不了张本智和这一关,国乒新秀差在哪儿?北京日报客户端记者王笑笑又是第一轮,又是2比3。在4月18日进行的WTT(世界乒乓球职业大联盟)澳门冠军赛男单首轮中,中国小将林诗栋不敌日本名将张本智和,遭遇对后者的两连败,没能以足坛疯狂一夜皇马20刷爆纪录,米兰16年后进4强,C罗锁喉黄牌北京时间4月19日,今天凌晨欧冠14决赛第二回合的比赛正式开打,最终皇马靠着罗德里戈的双响20击败切尔西,总比分40晋级四强AC米兰则是靠着吉鲁的将功补过11战平那不勒斯,总比分2输不起?孙铭徽15中2,提前退场骂胡明轩解说员不应该广厦队虽然是只排在了CBA积分榜第七名,但是,他们是上赛季总决赛亚军,进入CBA常规赛第三阶段之后,他们一败难求,成为CBA表现最火的球队,在季后赛四分之一决赛前,他们已经豪取11拒绝签约!2米25内线或投奔杜锋,场均1713,接班易建联指日可待近日,已经从澳大利亚联赛回国的周琦和刘传兴正在接受隔离,这两名球员也是今年休赛期里的大鱼,成为了联盟当中很多球队挣抢的对象。周琦就不用说了,只要新疆队同意放人,相信CBA绝大多数球年收入不到5000万,身在洛杉矶的小卡为何吸金能力还不如克莱?NBA常规赛已经结束,季后赛正在进行,首轮对决没有出现一丝意外,分区前四的球队全部晋级,看得出来,常规赛的战绩还是非常能够说明球队实力的,以下客上说起来简单,不过想要达成却非常难,全球第一!詹姆斯双喜临门,湖人选帅目标出炉,珍妮巴斯发声明最近,洛杉矶湖人队传出来很多消息,其中,也有很多关于詹姆斯和浓眉哥交易的传闻,美媒那边的NBA记者,也都在谣传詹姆斯要被交易了。禅师菲尔杰克逊,希望湖人交易送走詹姆斯,这个事情靠谱詹皇年收入超梅西C罗疯狂赚1。27亿美元!哈登库里杜兰特也进前十体育财经网站Sportico近日发布了2022年度全球运动员收入榜单,在收入排名前100位的榜单之上,NBA联盟湖人球员勒布朗詹姆斯以1。269亿美元的年收入登顶。运动员收入榜的前进攻第1!防守第1,谁能想到,拿着239万底薪,却是勇士效率之王太阳勇士会师西决!指日可待啊,保罗库里相遇的画面,想一想都让人激动不已!进攻第1!防守第1,谁能想到,拿着239万底薪,却是勇士效率之王勇士今年的季后赛,库里得分第1,维金斯篮板第
GQ盛典众星王一博被批没礼貌,185cm李现成小矮人,成毅变化大15日晚,GQ盛典红毯如约而至。虽然龚俊倪妮杨幂等GQ老搭档因故不能出席,但现场还是星光熠熠,请来了成毅王一博李现王鹤棣丁程鑫关晓彤白鹿吴宣仪张凌赫等明星助阵。群星璀璨,却也盖不住不可一世的谢娜,也走到了今天文范范编辑世界谢娜作为快乐大本营的当家主持人,几十年来的主持生涯让她人气暴涨。但一直以来,网友们对于这位知名女主持人的评价都是褒贬不一的,甚至呈现出两种极端要么非常喜欢她,要么非常有望冲击诺奖!这一现象触及宇宙诞生的秘密研究人员数了那些顺时针和逆时针的四面体,惊讶地发现它们的数量显著不同。图片来源MyriamWaresforQuantaMagazine最新研究表明,若将宇宙中四个星系连成一个四面体歌手董文华巅峰期因绯闻跌落神坛,感谢丈夫的不离不弃!1985年,年仅23岁的董文华,首次登上春晚的舞台,凭借一首十五的月亮一炮而红。从此以后,董文华的名字传遍了大街小巷,她也因此成为了家喻户晓的知名女歌手。1994年,董文华再一次凭男歌星华晨宇开700万兰博基尼,他的生活让人非常羡慕中国歌星许许多多,有男歌星,女歌星,他们都是非常受到人们喜爱的,男歌星比如有张杰,陈楚生,华晨宇等等,华晨宇是一个实力型的男歌星,他的唱功非常了得,深受大部分人的喜爱,今天我来说说人称塞外茅台的宁城老窖,曾火遍大江南北,如今为何没人喝?第一步,关注我!大家好,我是老黄!所谓一方水土养一方人,由于长期生活在兼得无尽沙漠与无垠草原的内蒙古,如沙漠烈阳般的热情,以及堪比草原般宽广的豪放,也慢慢成为了内蒙古人性格的一部分流行歌星夏奇拉拍摄的时尚杂志大片夏奇拉拍摄Elle美国版时尚杂志夏奇拉为Elle美国版的2022年10月号发行了一张数字封面。在摄影师JaumedeLaiguana的镜头下,她穿着一件FernandoClaro连走遍大江南北,我还是觉得苏州最美我不是苏州人,但我上完学以后就留在了苏州,本职工作是一名导游,带着苏州的客人游遍了祖国的大好河山,带着外地游客走遍了苏州的大街小巷,这两年做起了自媒体,探访了苏州很多很重要,但是很贵州3大倒霉酒,曾经风靡大江南北,如今却被名字耽搁无人识头条创作挑战赛万里黔中一漏天,屋居终日似乘船!贵州,西南三省之一,因古时地形崎岖,交通不便,运输东西成本昂贵,故称之为贵州。贵州地貌以山地高原为主,大自然的鬼斧神工,造就了贵州美景47款家常菜肴分享,真鲜美真好吃,抽空做几道尝尝吧曾经看到一篇文章中写道美食当前,总能有所思,或馋性千娇,食前观察吃中思想品后体煨,食为天性,静静地咀嚼,轻轻地回味,非比寻常的韵致。吃食是一种幸福,品味是一种情趣,而透明墨香感受文坐上高铁游蒙自天为罗帐地为毡满天星斗伴我眠即将开通的弥蒙高铁将彩云之南特有的热情奔放和深沉内敛融会贯通也给蒙自带来了新的发展契机蒙自正式进入高铁时代旅客朋友们今日蒙自微信公众号将推出5条精品旅游线路小编邀您留下来慢慢游今天
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网