XSS(Cross-Site Scripting,跨站腳本攻擊)是一種常見的 Web 攻擊技術(shù),攻擊者通過在 Web 頁面中插入惡意的腳本代碼,使得用戶在瀏覽頁面時(shí)執(zhí)行這些腳本,從而達(dá)到攻擊的目的。通常被分為如下的三種類型。
存儲型 XSS(Stored XSS)
攻擊者將惡意腳本代碼存儲在服務(wù)器上的數(shù)據(jù)庫或文件中,當(dāng)用戶訪問包含這些惡意代碼的頁面時(shí),會執(zhí)行這些代碼。
反射型 XSS(Reflected XSS)
攻擊者將惡意腳本代碼作為參數(shù)注入到URL中,當(dāng)用戶點(diǎn)擊包含這些惡意參數(shù)的URL時(shí),服務(wù)器端將參數(shù)反射回頁面并執(zhí)行,從而觸發(fā)XSS攻擊。
DOM 型 XSS(DOM-based XSS)
攻擊者利用客戶端腳本對DOM(Document Object Model,文檔對象模型)進(jìn)行操作的漏洞,通過修改頁面的DOM結(jié)構(gòu)來執(zhí)行惡意代碼。
SpringBoot可以通過使用過濾器或攔截器來對請求參數(shù)進(jìn)行過濾和清理,防止惡意的XSS腳本注入。下面是一種通過過濾器實(shí)現(xiàn)防止XSS攻擊的方法。
創(chuàng)建一個(gè)自定義的過濾器,用于過濾請求中的參數(shù),并清理其中的HTML標(biāo)簽和特殊字符。
@WebFilter("/*")
public class XSSFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化操作,可以留空
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(new XSSRequestWrapper((HttpServletRequest) request), response);
}
@Override
public void destroy() {
// 銷毀操作,可以留空
}
static class XSSRequestWrapper extends HttpServletRequestWrapper {
XSSRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String getParameter(String name) {
String value=super.getParameter(name);
if (value !=null) {
value=cleanXSS(value);
}
return value;
}
private String cleanXSS(String value) {
// 進(jìn)行 XSS 過濾,清理 HTML 標(biāo)簽和特殊字符
// 例如,可以使用正則表達(dá)式或者第三方庫進(jìn)行過濾
// 這里只是簡單示例,具體過濾規(guī)則需根據(jù)實(shí)際情況自行設(shè)計(jì)
return value.replaceAll("<", "<")
.replaceAll(">", ">")
.replaceAll("\"", """)
.replaceAll("'", "'")
.replaceAll("&", "&");
}
}
}
在SpringBoot應(yīng)用的配置類中注冊該過濾器。
@Bean
public FilterRegistrationBean<XSSFilter> xssFilterRegistration() {
FilterRegistrationBean<XSSFilter> registration=new FilterRegistrationBean<>();
registration.setFilter(new XSSFilter());
registration.addUrlPatterns("/*");
registration.setName("xssFilter");
registration.setOrder(1);
return registration;
}
上述代碼,我們創(chuàng)建了一個(gè)名為XSSFilter的過濾器,在doFilter方法中,對請求進(jìn)行過濾,并在需要時(shí)使用XSSRequestWrapper對請求參數(shù)進(jìn)行清理。清理過程中,我們簡單地將 HTML 標(biāo)簽和一些特殊字符替換為相應(yīng)的轉(zhuǎn)義序列,以防止惡意腳本注入。
請注意,這只是一種簡單的示例,實(shí)際場景中應(yīng)根據(jù)具體情況制定更為嚴(yán)格的過濾規(guī)則。
Thymeleaf是用于Web和獨(dú)立環(huán)境的現(xiàn)代服務(wù)器端Java模板引擎。能夠處理 HTML、XML、JavaScript、CSS 甚至純文本。
Thymeleaf 的主要目標(biāo)是提供一種優(yōu)雅且高度可維護(hù)的模板創(chuàng)建方式。為了實(shí)現(xiàn)這一點(diǎn),它建立在自然模板的概念之上,以不影響模板用作設(shè)計(jì)原型的方式將其邏輯注入模板文件。這改善了設(shè)計(jì)的溝通并彌合了設(shè)計(jì)和開發(fā)團(tuán)隊(duì)之間的差距。
Thymeleaf 的設(shè)計(jì)從一開始就考慮到了 Web 標(biāo)準(zhǔn)——尤其是 HTML5——允許您在需要時(shí)創(chuàng)建完全驗(yàn)證模板。
官網(wǎng)
https://www.thymeleaf.org/
官方文檔
https://www.thymeleaf.org/documentation.html
- th::利用H5的自定義屬性實(shí)現(xiàn),需要支持H5,不支持時(shí)需要使用data-th:代替
- ${...}:變量表達(dá)式,類似el表達(dá)式,獲取接口綁定的變量數(shù)據(jù)
- *{...}:選擇變量表達(dá)式,通常情況下與變量表達(dá)式一致,但是當(dāng)指定了變量后,可以使用選擇表達(dá)式直接引用對象的屬性名而不是通過對象.屬性
- #{...}:消息表達(dá)式,用于展示消息內(nèi)容,也可以引用變量內(nèi)容,常用于國際化
- @{...}:鏈接表達(dá)式,設(shè)置超鏈接時(shí)使用,與th:href等標(biāo)簽配合
- ~{...}:片段表達(dá)式,將重復(fù)使用的內(nèi)容提取出來引用
- th:id:替換標(biāo)簽的id屬性值,
- th:value:替換標(biāo)簽的value屬性值,該標(biāo)簽通常用于input標(biāo)簽中,為其value屬性賦值
- th:href:替換標(biāo)簽的href屬性值(a標(biāo)簽),<a th:href="@{index.html}">超鏈接</a>
- th:src:替換標(biāo)簽的src屬性值(img等標(biāo)簽),<script type="text/javascript" th:src="@{index.js}"></script>
- th:text:設(shè)置當(dāng)前元素的文本內(nèi)容,相同功能的還有th:utext,兩者的區(qū)別在于前者不會轉(zhuǎn)義html標(biāo)簽,后者會。優(yōu)先級不高:order=7。
- th:utext:支持使用html的文本替換當(dāng)前標(biāo)簽內(nèi)容
- th:object:替換標(biāo)簽中的對象
- th:each:遍歷變量中的值,迭代對象可以是java.util.List,java.util.Map,數(shù)組等數(shù)據(jù)類型;
- th:if:條件語句,取值應(yīng)為布爾類型,如果為false則當(dāng)前標(biāo)簽內(nèi)容不顯示
- th:unless:條件語句,取值應(yīng)為布爾類型,如果為true則當(dāng)前標(biāo)簽內(nèi)容不顯示
- th:switch:條件語句,取值對應(yīng)case內(nèi)容,只顯示對應(yīng)case標(biāo)簽
- th:case:請求返回綁定user對象的集合數(shù)據(jù),user對象包含name、age、gender等屬性,此時(shí)模板頁使用條件和遍歷標(biāo)簽渲染數(shù)據(jù)有以下形式。
整體代碼結(jié)構(gòu)如下:
在pom文件中引入freemarker,當(dāng)然在SpringBoot中是通過引入SpringBoot已經(jīng)提供好的starter。完整的pom依賴引入如下:
<dependencies>
<!-- thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
spring:
application:
name: springboot-thymeleaf
thymeleaf:
# 是否啟用模板緩存。
cache: false
# 是否檢查模板位置是否存在。
check-template: true
# 是否為Web框架啟用Thymeleaf視圖分辨率。
enabled: true
# 編碼格式, 默認(rèn)UTF-8
encoding: UTF-8
# 應(yīng)用于模板的模板模式。另請參閱Thymeleaf的TemplateMode枚舉。
mode: HTML
# 后綴 默認(rèn) .html
suffix: .html
# 模板文件存放位置 , 默認(rèn) classpath:/templates/
prefix: classpath:/templates/
我們建一個(gè)用戶實(shí)體
@Data
public class User {
private String username;
private Integer age;
private String email;
private String address;
}
創(chuàng)建Controller類并提供請求方法
@Controller
public class UserController {
@GetMapping("/")
public String getStudents(Model model) {
List<User> list=new ArrayList<>();
User userOne=new User();
userOne.setUsername("小明");
userOne.setAge(12);
userOne.setEmail("xxx@qq.com");
userOne.setAddress("安徽省合肥市");
list.add(userOne);
User userTwo=new User();
userTwo.setUsername("小紅");
userTwo.setAge(13);
userTwo.setEmail("xxx@126.com");
userTwo.setAddress("安徽省合肥市");
list.add(userTwo);
model.addAttribute("users", list);
return "users";
}
}
users.html頁面代碼如下:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table border="1">
<thead>
<tr>
<th>名稱</th>
<th>年齡</th>
<th>郵件</th>
<th>地址</th>
</tr>
</thead>
<tbody>
<!-- 遍歷集合,如果被遍歷的變量 users 為 null 或者不存在,則不會進(jìn)行遍歷,也不報(bào)錯(cuò)-->
<tr th:each="user : ${users}">
<td th:text="${user.username}"></td>
<td th:text="${user.age}"></td>
<td th:text="${user.email}"></td>
<td th:text="${user.address}"></td>
</tr>
</tbody>
</table>
</body>
</html>
啟動(dòng)項(xiàng)目,我們打開鏈接http://127.0.0.1:8080/。
篇文章跟大家簡單介紹了一下spring boot常用的集中模板引擎,因?yàn)閷roovy和mustache模板引擎了解的比較少,所以這兩個(gè)就沒給大家介紹,本次就簡單介紹一下這兩個(gè)模板引擎如何在spirng boot中使用。
Groovy:在我的了解中,groovy是一種兼容java的開發(fā)語言,我目前開發(fā)的項(xiàng)目就是使用的Grails框架結(jié)合groovy語言。但是使用這個(gè)模板引擎還是第一次用。網(wǎng)上是這樣說的:Groovy語言包含了一個(gè)模板引擎功能,可以生成各種類型的格式化文件,非常方便。模板引擎有下面幾個(gè),它們都實(shí)現(xiàn)了Template接口:
SimpleTemplateEngine - 基本的模板
StreamingTemplateEngine - 功能和 SimpleTemplateEngine相同,不過支持大于64k的模板
GStringTemplateEngine - 將模板保存為可寫的閉包,在流式場景中很有用
XmlTemplateEngine - 輸出XML文件的模板引擎
MarkupTemplateEngine - 一個(gè)完整的、優(yōu)化過的模板引擎,可以用于生成HTML等模板
代碼格式和方法
標(biāo)記模板其實(shí)是合法的Groovy代碼。
yieldUnescaped '<!DOCTYPE html>'
html(lang:'en') {
head {
meta('http-equiv':'"Content-Type" content="text/html; charset=utf-8"')
title('My page')
}
body {
p('This is an example of HTML contents')
}
}
常用的方法:
yieldUnescaped方法會直接輸出給定的語句,不轉(zhuǎn)義其中的字符。
yield方法和上面相反,會轉(zhuǎn)義特殊字符。
head這些HTML標(biāo)簽方法會生成對應(yīng)的標(biāo)簽。
xmlDeclaration()方法會生成一個(gè)標(biāo)準(zhǔn)的XML文檔頭。
comment方法生成HTML注釋。
newLine生成一個(gè)新行。
如何在spring boot中使用這個(gè)模板引擎呢?
pom中添加依賴
2.controller
3.新建indexg.tpl,groovy模板頁面擴(kuò)展名是tpl
和平常所見到的頁面結(jié)構(gòu)不太一樣,想要學(xué)習(xí)這個(gè)技術(shù)的可以直接訪問圖片中的鏈接,查看官方文檔學(xué)習(xí)。
4.運(yùn)行結(jié)果
Mustache:mustache官方給出的是Logic-less templates.翻譯過來就是邏輯很少的模板,Mustcache可以被用于html文件,配置文件,源代碼等等很多場景,它的運(yùn)行得益于擴(kuò)展一些標(biāo)簽在模板文件中,然后使用一個(gè)hash字典或者對象對其進(jìn)行替換渲染。我們之所以稱之為“l(fā)ogic-less”是因?yàn)樗饤壛薸f else 以及for loop 這樣的語句,取而代之的是只有標(biāo)簽,有些標(biāo)簽被替換成一個(gè)值,或者不作為,或者是一系列的值,比如數(shù)組或者一個(gè)列表,標(biāo)簽有幾種不同的類型,自接下來我們會逐個(gè)介紹,但是你要相信他非常簡單,因?yàn)樗恰發(fā)ogic-less”的。(摘自wangwenjun69的csdn博客)
這個(gè)模板我也不是很了解,就簡單介紹一下如何在spring boot中使用
pom中引入依賴
2.controller
3.新建indexm.html
4.訪問
至此,spring boot中推薦的5種模板引擎就介紹完了,都是最簡單的應(yīng)用,希望對入門的朋友有所幫助。
*請認(rèn)真填寫需求信息,我們會在24小時(shí)內(nèi)與您取得聯(lián)系。