如何过滤xss攻击

时间:2022-12-06 01:27

如何过滤xss攻击

过滤xss攻击的方法:

1.XSS过滤器示例代码:

packagecom.devframe.filter;importjavax.servlet.*;

importjavax.servlet.http.HttpServletRequest;

importjava.io.IOException;publicclassXssFilterimplementsFilter{@Override

publicvoidinit(FilterConfigconfig){

}@Override

publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)

throwsIOException,ServletException{

XssHttpServletRequestWrapperxssRequest=newXssHttpServletRequestWrapper(

(HttpServletRequest)request);

chain.doFilter(xssRequest,response);

}@Override

publicvoiddestroy(){

}}

2.request进行XSS过滤,代码:

packagecom.devframe.filter;importorg.apache.commons.io.IOUtils;

importorg.springframework.http.HttpHeaders;

importorg.springframework.http.MediaType;

importorg.springframework.util.StringUtils;importjavax.servlet.ReadListener;

importjavax.servlet.ServletInputStream;

importjavax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpServletRequestWrapper;

importjava.io.ByteArrayInputStream;

importjava.io.IOException;

importjava.util.LinkedHashMap;

importjava.util.Map;publicclassXssHttpServletRequestWrapperextendsHttpServletRequestWrapper{

/**

*没被包装过的HttpServletRequest(特殊场景,需要自己过滤)

*/

privateHttpServletRequestorgRequest;

/**

*html过滤

*/

privatefinalstaticHTMLFilterHTML_FILTER=newHTMLFilter();

/**

*Constructsarequestobjectwrappingthegivenrequest.

*

*@paramrequestrequest

*@throwsIllegalArgumentExceptioniftherequestisnull

*/

XssHttpServletRequestWrapper(HttpServletRequestrequest)throwsIllegalArgumentException{

super(request);

orgRequest=request;

}@Override

publicServletInputStreamgetInputStream()throwsIOException{

//非json类型,直接返回

if(!super.getHeader(HttpHeaders.CONTENT_TYPE).equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE)){

returnsuper.getInputStream();

}//为空,直接返回

Stringjson=IOUtils.toString(super.getInputStream(),"utf-8");

if(!StringUtils.hasText(json)){

returnsuper.getInputStream();

}//xss过滤

json=xssEncode(json);

finalByteArrayInputStreambis=newByteArrayInputStream(json.getBytes("utf-8"));

returnnewServletInputStream(){

@Override

publicbooleanisFinished(){

returntrue;

}@Override

publicbooleanisReady(){

returntrue;

}@Override

publicvoidsetReadListener(ReadListenerreadListener){

}@Override

publicintread(){

returnbis.read();

}

};

}/**

*过滤参数

*@paramname参数name,也要过滤

*@returnStringvalue

*/

@Override

publicStringgetParameter(Stringname){

Stringvalue=super.getParameter(xssEncode(name));

if(StringUtils.hasText(value)){

value=xssEncode(value);

}

returnvalue;

}/**

*过滤参数,值为数组

*@paramname参数名

*@returnString[]

*/

@Override

publicString[]getParameterValues(Stringname){

String[]parameters=super.getParameterValues(name);

if(parameters==null||parameters.length==0){

returnnull;

}for(inti=0;i<parameters.length;i++){

parameters[i]=xssEncode(parameters[i]);

}

returnparameters;

}/**

*过滤参数,返回键值对形式的参数类型

*@returnMap

*/

@Override

publicMap<String,String[]>getParameterMap(){

Map<String,String[]>map=newLinkedHashMap<>();

Map<String,String[]>parameters=super.getParameterMap();

for(Stringkey:parameters.keySet()){

String[]values=parameters.get(key);

for(inti=0;i<values.length;i++){

values[i]=xssEncode(values[i]);

}

map.put(key,values);

}

returnmap;

}/**

*获取request的头属性,并且进行xss过滤,返回它的值

*@paramname属性名

*@returnString值

*/

@Override

publicStringgetHeader(Stringname){

Stringvalue=super.getHeader(xssEncode(name));

if(StringUtils.hasText(value)){

value=xssEncode(value);

}

returnvalue;

}privateStringxssEncode(Stringinput){

returnHTML_FILTER.filter(input);

}/**

*获取最原始的request

*@returnHttpServletRequest原始的request

*/

publicHttpServletRequestgetOrgRequest(){

returnorgRequest;

}/**

*获取最原始的request,明确不进行xss过滤的

*@paramrequestrequest

*@returnHttpServletRequest原始request

*/

publicstaticHttpServletRequestgetOrgRequest(HttpServletRequestrequest){

if(requestinstanceofXssHttpServletRequestWrapper){

return((XssHttpServletRequestWrapper)request).getOrgRequest();

}

returnrequest;

}

}

3.XSS过滤工具类,示例代码:

packagecom.devframe.filter;importjava.util.*;

importjava.util.concurrent.ConcurrentHashMap;

importjava.util.concurrent.ConcurrentMap;

importjava.util.logging.Logger;

importjava.util.regex.Matcher;

importjava.util.regex.Pattern;/**

*

*HTMLfilteringutilityforprotectingagainstXSS(CrossSiteScripting).

*

*ThiscodeislicensedLGPLv3

*

*ThiscodeisaJavaportoftheoriginalworkinPHPbyCalHendersen.

*http://code.iamcal.com/php/lib_filter/

*

*Thetrickiestpartofthetranslationwashandlingthedifferencesinregexhandling

*betweenPHPandJava.Theseresourceswerehelpfulintheprocess:

*

*http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/Pattern.html

*http://us2.php.net/manual/en/reference.pcre.pattern.modifiers.php

*http://www.regular-expressions.info/modifiers.html

*

*Anoteonnamingconventions:instancevariablesareprefixedwitha"v";global

*constantsareinallcaps.

*

*Sampleuse:

*Stringinput=...

*Stringclean=newHTMLFilter().filter(input);

*

*Theclassisnotthreadsafe.Createanewinstanceifindoubt.

*

*Ifyoufindbugsorhavesuggestionsonimprovement(especiallyregarding

*performance),pleasecontactus.Thelatestversionofthis

*source,andourcontactdetails,canbefoundathttp://xss-html-filter.sf.net

*

*@authorJosephO'Connell

*@authorCalHendersen

*@authorMichaelSembWever

*/

publicfinalclassHTMLFilter{/**regexflagunionrepresenting/simodifiersinphp**/

privatestaticfinalintREGEX_FLAGS_SI=Pattern.CASE_INSENSITIVE|Pattern.DOTALL;

privatestaticfinalPatternP_COMMENTS=Pattern.compile("<!--(.*?)-->",Pattern.DOTALL);

privatestaticfinalPatternP_COMMENT=Pattern.compile("^!--(.*)--$",REGEX_FLAGS_SI);

privatestaticfinalPatternP_TAGS=Pattern.compile("<(.*?)>",Pattern.DOTALL);

privatestaticfinalPatternP_END_TAG=Pattern.compile("^/([a-z0-9]+)",REGEX_FLAGS_SI);

privatestaticfinalPatternP_START_TAG=Pattern.compile("^([a-z0-9]+)(.*?)(/?)$",REGEX_FLAGS_SI);

privatestaticfinalPatternP_QUOTED_ATTRIBUTES=Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2",REGEX_FLAGS_SI);

privatestaticfinalPatternP_UNQUOTED_ATTRIBUTES=Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)",REGEX_FLAGS_SI);

privatestaticfinalPatternP_PROTOCOL=Pattern.compile("^([^:]+):",REGEX_FLAGS_SI);

privatestaticfinalPatternP_ENTITY=Pattern.compile("&#(\\d+);?");

privatestaticfinalPatternP_ENTITY_UNICODE=Pattern.compile("&#x([0-9a-f]+);?");

privatestaticfinalPatternP_ENCODE=Pattern.compile("%([0-9a-f]{2});?");

privatestaticfinalPatternP_VALID_ENTITIES=Pattern.compile("&([^&;]*)(?=(;|&|$))");

privatestaticfinalPatternP_VALID_QUOTES=Pattern.compile("(>|^)([^<]+?)(<|$)",Pattern.DOTALL);

privatestaticfinalPatternP_END_ARROW=Pattern.compile("^>");

privatestaticfinalPatternP_BODY_TO_END=Pattern.compile("<([^>]*?)(?=<|$)");

privatestaticfinalPatternP_XML_CONTENT=Pattern.compile("(^|>)([^<]*?)(?=>)");

privatestaticfinalPatternP_STRAY_LEFT_ARROW=Pattern.compile("<([^>]*?)(?=<|$)");

privatestaticfinalPatternP_STRAY_RIGHT_ARROW=Pattern.compile("(^|>)([^<]*?)(?=>)");

privatestaticfinalPatternP_AMP=Pattern.compile("&");

privatestaticfinalPatternP_QUOTE=Pattern.compile("<");

privatestaticfinalPatternP_LEFT_ARROW=Pattern.compile("<");

privatestaticfinalPatternP_RIGHT_ARROW=Pattern.compile(">");

privatestaticfinalPatternP_BOTH_ARROWS=Pattern.compile("<>");//@xxxcouldgrowlarge...maybeusesesat'sReferenceMap

privatestaticfinalConcurrentMap<String,Pattern>P_REMOVE_PAIR_BLANKS=newConcurrentHashMap<String,Pattern>();

privatestaticfinalConcurrentMap<String,Pattern>P_REMOVE_SELF_BLANKS=newConcurrentHashMap<String,Pattern>();/**setofallowedhtmlelements,alongwithallowedattributesforeachelement**/

privatefinalMap<String,List<String>>vAllowed;

/**countsofopentagsforeach(allowable)htmlelement**/

privatefinalMap<String,Integer>vTagCounts=newHashMap<String,Integer>();/**htmlelementswhichmustalwaysbeself-closing(e.g."<img/>")**/

privatefinalString[]vSelfClosingTags;

/**htmlelementswhichmustalwayshaveseparateopeningandclosingtags(e.g."<b></b>")**/

privatefinalString[]vNeedClosingTags;

/**setofdisallowedhtmlelements**/

privatefinalString[]vDisallowed;

/**attributeswhichshouldbecheckedforvalidprotocols**/

privatefinalString[]vProtocolAtts;

/**allowedprotocols**/

privatefinalString[]vAllowedProtocols;

/**tagswhichshouldberemovediftheycontainnocontent(e.g."<b></b>"or"<b/>")**/

privatefinalString[]vRemoveBlanks;

/**entitiesallowedwithinhtmlmarkup**/

privatefinalString[]vAllowedEntities;

/**flagdeterminingwhethercommentsareallowedininputString.*/

privatefinalbooleanstripComment;

privatefinalbooleanencodeQuotes;

privatebooleanvDebug=false;

/**

*flagdeterminingwhethertotrytomaketagswhenpresentedwith"unbalanced"

*anglebrackets(e.g."<btext</b>"becomes"<b>text</b>").Ifsettofalse,

*unbalancedanglebracketswillbehtmlescaped.

*/

privatefinalbooleanalwaysMakeTags;/**Defaultconstructor.

*

*/

publicHTMLFilter(){

vAllowed=newHashMap<>();finalArrayList<String>a_atts=newArrayList<String>();

a_atts.add("href");

a_atts.add("target");

vAllowed.put("a",a_atts);finalArrayList<String>img_atts=newArrayList<String>();

img_atts.add("src");

img_atts.add("width");

img_atts.add("height");

img_atts.add("alt");

vAllowed.put("img",img_atts);finalArrayList<String>no_atts=newArrayList<String>();

vAllowed.put("b",no_atts);

vAllowed.put("strong",no_atts);

vAllowed.put("i",no_atts);

vAllowed.put("em",no_atts);vSelfClosingTags=newString[]{"img"};

vNeedClosingTags=newString[]{"a","b","strong","i","em"};

vDisallowed=newString[]{};

vAllowedProtocols=newString[]{"http","mailto","https"};//noftp.

vProtocolAtts=newString[]{"src","href"};

vRemoveBlanks=newString[]{"a","b","strong","i","em"};

vAllowedEntities=newString[]{"amp","gt","lt","quot"};

stripComment=true;

encodeQuotes=true;

alwaysMakeTags=true;

}/**Setdebugflagtotrue.Otherwiseusedefaultsettings.Seethedefaultconstructor.

*

*@paramdebugturndebugonwithatrueargument

*/

publicHTMLFilter(finalbooleandebug){

this();

vDebug=debug;}/**Map-parameterconfigurableconstructor.

*

*@paramconfmapcontainingconfiguration.keysmatchfieldnames.

*/

publicHTMLFilter(finalMap<String,Object>conf){assertconf.containsKey("vAllowed"):"configurationrequiresvAllowed";

assertconf.containsKey("vSelfClosingTags"):"configurationrequiresvSelfClosingTags";

assertconf.containsKey("vNeedClosingTags"):"configurationrequiresvNeedClosingTags";

assertconf.containsKey("vDisallowed"):"configurationrequiresvDisallowed";

assertconf.containsKey("vAllowedProtocols"):"configurationrequiresvAllowedProtocols";

assertconf.containsKey("vProtocolAtts"):"configurationrequiresvProtocolAtts";

assertconf.containsKey("vRemoveBlanks"):"configurationrequiresvRemoveBlanks";

assertconf.containsKey("vAllowedEntities"):"configurationrequiresvAllowedEntities";vAllowed=Collections.unmodifiableMap((HashMap<String,List<String>>)conf.get("vAllowed"));

vSelfClosingTags=(String[])conf.get("vSelfClosingTags");

vNeedClosingTags=(String[])conf.get("vNeedClosingTags");

vDisallowed=(String[])conf.get("vDisallowed");

vAllowedProtocols=(String[])conf.get("vAllowedProtocols");

vProtocolAtts=(String[])conf.get("vProtocolAtts");

vRemoveBlanks=(String[])conf.get("vRemoveBlanks");

vAllowedEntities=(String[])conf.get("vAllowedEntities");

stripComment=conf.containsKey("stripComment")?(Boolean)conf.get("stripComment"):true;

encodeQuotes=conf.containsKey("encodeQuotes")?(Boolean)conf.get("encodeQuotes"):true;

alwaysMakeTags=conf.containsKey("alwaysMakeTags")?(Boolean)conf.get("alwaysMakeTags"):true;

}privatevoidreset(){

vTagCounts.clear();

}privatevoiddebug(finalStringmsg){

if(vDebug){

Logger.getAnonymousLogger().info(msg);

}

}//---------------------------------------------------------------

//myversionsofsomePHPlibraryfunctions

publicstaticStringchr(finalintdecimal){

returnString.valueOf((char)decimal);

}publicstaticStringhtmlSpecialChars(finalStrings){

Stringresult=s;

result=regexReplace(P_AMP,"&",result);

result=regexReplace(P_QUOTE,""",result);

result=regexReplace(P_LEFT_ARROW,"<",result);

result=regexReplace(P_RIGHT_ARROW,">",result);

returnresult;

}//---------------------------------------------------------------

/**

*givenausersubmittedinputString,filteroutanyinvalidorrestricted

*html.

*

*@paraminputtext(i.e.submittedbyauser)thanmaycontainhtml

*@return"clean"versionofinput,withonlyvalid,whitelistedhtmlelementsallowed

*/

publicStringfilter(finalStringinput){

reset();

Strings=input;debug("************************************************");

debug("INPUT:"+input);s=escapeComments(s);

debug("escapeComments:"+s);s=balanceHTML(s);

debug("balanceHTML:"+s);s=checkTags(s);

debug("checkTags:"+s);s=processRemoveBlanks(s);

debug("processRemoveBlanks:"+s);s=validateEntities(s);

debug("validateEntites:"+s);debug("************************************************\n\n");

returns;

}publicbooleanisAlwaysMakeTags(){

returnalwaysMakeTags;

}publicbooleanisStripComments(){

returnstripComment;

}privateStringescapeComments(finalStrings){

finalMatcherm=P_COMMENTS.matcher(s);

finalStringBufferbuf=newStringBuffer();

if(m.find()){

finalStringmatch=m.group(1);//(.*?)

m.appendReplacement(buf,Matcher.quoteReplacement("<!--"+htmlSpecialChars(match)+"-->"));

}

m.appendTail(buf);returnbuf.toString();

}privateStringbalanceHTML(Strings){

if(alwaysMakeTags){

//

//tryandformhtml

//

s=regexReplace(P_END_ARROW,"",s);

s=regexReplace(P_BODY_TO_END,"<$1>",s);

s=regexReplace(P_XML_CONTENT,"$1<$2",s);}else{

//

//escapestraybrackets

//

s=regexReplace(P_STRAY_LEFT_ARROW,"<$1",s);

s=regexReplace(P_STRAY_RIGHT_ARROW,"$1$2><",s);//

//thelastregexpcauses'<>'entitiestoappear

//(weneedtodoalookaheadassertionsothatthelastbracketcan

//beusedinthenextpassoftheregexp)

//

s=regexReplace(P_BOTH_ARROWS,"",s);

}returns;

}privateStringcheckTags(Strings){

Matcherm=P_TAGS.matcher(s);finalStringBufferbuf=newStringBuffer();

while(m.find()){

StringreplaceStr=m.group(1);

replaceStr=processTag(replaceStr);

m.appendReplacement(buf,Matcher.quoteReplacement(replaceStr));

}

m.appendTail(buf);s=buf.toString();//thesegettalliedinprocessTag

//(remembertoresetbeforesubsequentcallstofiltermethod)

for(Stringkey:vTagCounts.keySet()){

for(intii=0;ii<vTagCounts.get(key);ii++){

s+="</"+key+">";

}

}returns;

}privateStringprocessRemoveBlanks(finalStrings){

Stringresult=s;

for(Stringtag:vRemoveBlanks){

if(!P_REMOVE_PAIR_BLANKS.containsKey(tag)){

P_REMOVE_PAIR_BLANKS.putIfAbsent(tag,Pattern.compile("<"+tag+"(\\s[^>]*)?></"+tag+">"));

}

result=regexReplace(P_REMOVE_PAIR_BLANKS.get(tag),"",result);

if(!P_REMOVE_SELF_BLANKS.containsKey(tag)){

P_REMOVE_SELF_BLANKS.putIfAbsent(tag,Pattern.compile("<"+tag+"(\\s[^>]*)?/>"));

}

result=regexReplace(P_REMOVE_SELF_BLANKS.get(tag),"",result);

}returnresult;

}privatestaticStringregexReplace(finalPatternregex_pattern,finalStringreplacement,finalStrings){

Matcherm=regex_pattern.matcher(s);

returnm.replaceAll(replacement);

}privateStringprocessTag(finalStrings){

//endingtags

Matcherm=P_END_TAG.matcher(s);

if(m.find()){

finalStringname=m.group(1).toLowerCase();

if(allowed(name)){

if(!inArray(name,vSelfClosingTags)){

if(vTagCounts.containsKey(name)){

vTagCounts.put(name,vTagCounts.get(name)-1);

return"</"+name+">";

}

}

}

}//startingtags

m=P_START_TAG.matcher(s);

if(m.find()){

finalStringname=m.group(1).toLowerCase();

finalStringbody=m.group(2);

Stringending=m.group(3);//debug("inastartingtag,name='"+name+"';body='"+body+"';ending='"+ending+"'");

if(allowed(name)){

Stringparams="";finalMatcherm2=P_QUOTED_ATTRIBUTES.matcher(body);

finalMatcherm3=P_UNQUOTED_ATTRIBUTES.matcher(body);

finalList<String>paramNames=newArrayList<String>();

finalList<String>paramValues=newArrayList<String>();

while(m2.find()){

paramNames.add(m2.group(1));//([a-z0-9]+)

paramValues.add(m2.group(3));//(.*?)

}

while(m3.find()){

paramNames.add(m3.group(1));//([a-z0-9]+)

paramValues.add(m3.group(3));//([^\"\\s']+)

}StringparamName,paramValue;

for(intii=0;ii<paramNames.size();ii++){

paramName=paramNames.get(ii).toLowerCase();

paramValue=paramValues.get(ii);//debug("paramName='"+paramName+"'");

//debug("paramValue='"+paramValue+"'");

//debug("allowed?"+vAllowed.get(name).contains(paramName));if(allowedAttribute(name,paramName)){

if(inArray(paramName,vProtocolAtts)){

paramValue=processParamProtocol(paramValue);

}

params+=""+paramName+"=\""+paramValue+"\"";

}

}if(inArray(name,vSelfClosingTags)){

ending="/";

}if(inArray(name,vNeedClosingTags)){

ending="";

}if(ending==null||ending.length()<1){

if(vTagCounts.containsKey(name)){

vTagCounts.put(name,vTagCounts.get(name)+1);

}else{

vTagCounts.put(name,1);

}

}else{

ending="/";

}

return"<"+name+params+ending+">";

}else{

return"";

}

}//comments

m=P_COMMENT.matcher(s);

if(!stripComment&&m.find()){

return"<"+m.group()+">";

}return"";

}privateStringprocessParamProtocol(Strings){

s=decodeEntities(s);

finalMatcherm=P_PROTOCOL.matcher(s);

if(m.find()){

finalStringprotocol=m.group(1);

if(!inArray(protocol,vAllowedProtocols)){

//badprotocol,turnintolocalanchorlinkinstead

s="#"+s.substring(protocol.length()+1,s.length());

if(s.startsWith("#//")){

s="#"+s.substring(3,s.length());

}

}

}returns;

}privateStringdecodeEntities(Strings){

StringBufferbuf=newStringBuffer();Matcherm=P_ENTITY.matcher(s);

while(m.find()){

finalStringmatch=m.group(1);

finalintdecimal=Integer.decode(match).intValue();

m.appendReplacement(buf,Matcher.quoteReplacement(chr(decimal)));

}

m.appendTail(buf);

s=buf.toString();buf=newStringBuffer();

m=P_ENTITY_UNICODE.matcher(s);

while(m.find()){

finalStringmatch=m.group(1);

finalintdecimal=Integer.valueOf(match,16).intValue();

m.appendReplacement(buf,Matcher.quoteReplacement(chr(decimal)));

}

m.appendTail(buf);

s=buf.toString();buf=newStringBuffer();

m=P_ENCODE.matcher(s);

while(m.find()){

finalStringmatch=m.group(1);

finalintdecimal=Integer.valueOf(match,16).intValue();

m.appendReplacement(buf,Matcher.quoteReplacement(chr(decimal)));

}

m.appendTail(buf);

s=buf.toString();s=validateEntities(s);

returns;

}privateStringvalidateEntities(finalStrings){

StringBufferbuf=newStringBuffer();//validateentitiesthroughoutthestring

Matcherm=P_VALID_ENTITIES.matcher(s);

while(m.find()){

finalStringone=m.group(1);//([^&;]*)

finalStringtwo=m.group(2);//(?=(;|&|$))

m.appendReplacement(buf,Matcher.quoteReplacement(checkEntity(one,two)));

}

m.appendTail(buf);returnencodeQuotes(buf.toString());

}privateStringencodeQuotes(finalStrings){

if(encodeQuotes){

StringBufferbuf=newStringBuffer();

Matcherm=P_VALID_QUOTES.matcher(s);

while(m.find()){

finalStringone=m.group(1);//(>|^)

finalStringtwo=m.group(2);//([^<]+?)

finalStringthree=m.group(3);//(<|$)

m.appendReplacement(buf,Matcher.quoteReplacement(one+regexReplace(P_QUOTE,""",two)+three));

}

m.appendTail(buf);

returnbuf.toString();

}else{

returns;

}

}privateStringcheckEntity(finalStringpreamble,finalStringterm){return";".equals(term)&&isValidEntity(preamble)

?'&'+preamble

:"&"+preamble;

}privatebooleanisValidEntity(finalStringentity){

returninArray(entity,vAllowedEntities);

}privatestaticbooleaninArray(finalStrings,finalString[]array){

for(Stringitem:array){

if(item!=null&&item.equals(s)){

returntrue;

}

}

returnfalse;

}privatebooleanallowed(finalStringname){

return(vAllowed.isEmpty()||vAllowed.containsKey(name))&&!inArray(name,vDisallowed);

}privatebooleanallowedAttribute(finalStringname,finalStringparamName){

returnallowed(name)&&(vAllowed.isEmpty()||vAllowed.get(name).contains(paramName));

}

}

在web.xml配置filter的使用示例:

<filter>

<filter-name>xssFilter</filter-name>

<filter-class>com.devframe.filter.XssFilter</filter-class>

</filter><filter-mapping>

<filter-name>xssFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>


标签:
随便看看
本类推荐
本类排行
热门标签

我国国家通讯社行不行啊细狗新年贺词祝福语2023年祝福语新年新年贺词新年贺词祝福语居家抗病毒小药箱除夕高速免费吗2022年除夕高速免费吗春联春联句子大全春联句子大全七字年夜饭十二道菜年夜饭十二道菜单年夜饭吃什么年夜饭吃什么菜吃年夜饭的寓意年夜饭黑芝麻菊花茶晒菊花茶腌腊肉送妈妈生日礼物汉白玉送闺蜜水钻送女人礼物爸爸生日送礼物送老公