赞
踩
HTML 是网页的基础结构语言,而 Vue.js 是一个用于构建用户界面的渐进式JavaScript框架。结合两者,你可以创建动态、响应式的Web应用程序。Vue.js通过指令(如v-bind
, v-if
, v-for
)无缝集成到HTML中,使得数据绑定和页面逻辑变得更加直观。
示例:
- <div id="app">
- <h1>{{ message }}</h1>
- <input v-model="message">
- </div>
-
- <script src="https://cdn.jsdelivr.net/npm/vue"></script>
- <script>
- new Vue({
- el: '#app',
- data: {
- message: 'Hello Vue!'
- }
- })
- </script>
在前后端分离的架构中,Vue.js 负责前端展示与交互,而 Spring Boot 提供后端服务。两者通常通过API进行通信,常用的技术栈包括 RESTful API 和 Axios(Vue端的HTTP库)。
Vue.js 请求Spring Boot API示例:
- axios.get('http://localhost:8080/api/users')
- .then(response => {
- this.users = response.data;
- })
- .catch(error => {
- console.error("Error fetching data: ", error);
- });
MyBatis 是一个优秀的持久层框架,它支持自定义SQL,可以将SQL查询映射到Java对象。在Spring Boot中,通过MyBatis-Spring-Boot-Starter可以轻松集成。
配置示例(application.yml
或application.properties
):
- mybatis.type-aliases-package=com.example.demo.entity
- mybatis.mapper-locations=classpath:mapper/*.xml
重写(Overriding):在继承关系中,子类可以提供一个与其父类方法签名完全相同的方法实现。这允许子类改变父类的行为。重写要求方法名、参数列表、返回类型必须与父类方法一致,且访问权限不能比父类更严格。
重载(Overloading):发生在同一个类中,方法名相同但参数列表不同(参数类型、数量或顺序不同)。重载方法可以有不同的返回类型,但这是根据参数列表区分的,而不是返回类型。
自定义类型处理器允许你改变MyBatis处理特定类型数据的方式,例如,自定义字符串类型处理器来处理特殊格式的数据。
示例:
- package com.example.mapper.handlers;
-
- import org.apache.ibatis.type.BaseTypeHandler;
- import org.apache.ibatis.type.JdbcType;
- import org.apache.ibatis.type.MappedTypes;
-
- import java.sql.CallableStatement;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
-
- @MappedTypes(String.class)
- public class CustomStringTypeHandler extends BaseTypeHandler<String> {
-
- @Override
- public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
- ps.setString(i, customProcess(parameter));
- }
-
- @Override
- public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
- return customProcess(rs.getString(columnName));
- }
-
- @Override
- public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
- return customProcess(rs.getString(columnIndex));
- }
-
- @Override
- public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
- return customProcess(cs.getString(columnIndex));
- }
-
- private String customProcess(String input) {
- // 在这里实现你的自定义处理逻辑
- return input.toUpperCase(); // 示例:将字符串转为大写
- }
- }
通过以上示例,你可以看到如何将这些技术结合起来,构建一个从前端展示到后端数据处理的完整Web应用流程。从Vue.js的前端界面到Spring Boot后端服务,再到MyBatis处理数据库交互,每一步都是现代Web应用开发的关键环节。
在Web应用开发中,Thymeleaf 作为模板引擎常用于Spring Boot项目中,Vue.js 则用于构建动态的前端界面。当结合MyBatis和Spring Boot后端进行数据库操作时,防范SQL注入攻击是至关重要的。以下是一个结合Thymeleaf、Vue.js、MyBatis和Spring Boot的示例,通过一个登录功能,来具体说明SQL注入攻击及其预防方法。
首先,我们看前端如何接收用户输入并提交到后端。
- <!-- login.vue -->
- <template>
- <form @submit.prevent="login">
- <input type="text" v-model="username" placeholder="Username" />
- <input type="password" v-model="password" placeholder="Password" />
- <button>Login</button>
- </form>
- </template>
-
- <script>
- export default {
- data() {
- return {
- username: '',
- password: ''
- };
- },
- methods: {
- async login() {
- await axios.post('/api/login', { username: this.username, password: this.password });
- }
- }
- };
- </script>
- <!-- login.html -->
- <form th:action="@{/api/login}" method="post">
- <input type="text" name="username" placeholder="Username" />
- <input type="password" name="password" placeholder="Password" />
- <button type="submit">Login</button>
- </form>
后端接收到前端提交的数据后,需要正确处理以防止SQL注入。
- // UserController.java
- @PostMapping("/api/login")
- public ResponseEntity<?> login(@RequestParam String username, @RequestParam String password) {
- User user = userService.login(username, password);
- if (user != null) {
- return ResponseEntity.ok("Login successful");
- } else {
- return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid credentials");
- }
- }
-
- // UserService.java
- public User login(String username, String password) {
- String query = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'";
- return jdbcTemplate.queryForObject(query, new UserRowMapper());
- }
使用MyBatis的Mapper接口和PreparedStatement来防止SQL注入。
- // UserMapper.java
- @Mapper
- public interface UserMapper {
- @Select("SELECT * FROM users WHERE username = #{username} AND password = #{password}")
- User findByUsernameAndPassword(@Param("username") String username, @Param("password") String password);
- }
-
- // UserService.java
- @Service
- public class UserService {
- @Autowired
- private UserMapper userMapper;
-
- public User login(String username, String password) {
- return userMapper.findByUsernameAndPassword(username, password);
- }
- }
- CREATE TABLE `users` (
- `id` INT(11) NOT NULL AUTO_INCREMENT,
- `username` VARCHAR(255) NOT NULL,
- `password` VARCHAR(255) NOT NULL, -- 实际存储的是密码的哈希值
- `email` VARCHAR(255),
- `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
- `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
- PRIMARY KEY (`id`),
- UNIQUE KEY `uk_username` (`username`) -- 确保用户名唯一
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
- package com.example.demo.entity;
-
- import java.time.LocalDateTime;
-
- public class User {
- private Integer id;
- private String username;
- private String password; // 存储的是密码的哈希值
- private String email;
- private LocalDateTime createdAt;
- private LocalDateTime updatedAt;
-
- // Getter and Setter methods
- public Integer getId() {
- return id;
- }
-
- public void setId(Integer id) {
- this.id = id;
- }
-
- public String getUsername() {
- return username;
- }
-
- public void setUsername(String username) {
- this.username = username;
- }
-
- public String getPassword() {
- return password;
- }
-
- public void setPassword(String password) {
- this.password = password; // 实际应用中,这里应该是设置密码的哈希值
- }
-
- public String getEmail() {
- return email;
- }
-
- public void setEmail(String email) {
- this.email = email;
- }
-
- public LocalDateTime getCreatedAt() {
- return createdAt;
- }
-
- public void setCreatedAt(LocalDateTime createdAt) {
- this.createdAt = createdAt;
- }
-
- public LocalDateTime getUpdatedAt() {
- return updatedAt;
- }
-
- public void setUpdatedAt(LocalDateTime updatedAt) {
- this.updatedAt = updatedAt;
- }
- }
在不安全的示例中,直接拼接SQL字符串,如果用户输入为 admin' OR '1'='1
作为用户名,任何密码都会导致SQL语句变为
WHERE username = 'admin' OR '1'='1' AND password = '...'
,因为 '1'='1'
永远为真,所以该查询会匹配所有用户,造成SQL注入攻击。
而在安全示例中,通过MyBatis的#{}
语法和PreparedStatement,框架会自动对参数进行转义,确保特殊字符被安全处理,防止了SQL注入的发生。
结合Vue.js或Thymeleaf的前端界面,使用Spring Boot和MyBatis构建后端时,务必采用参数化查询来防止SQL注入,确保应用的安全性。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。