SpringBoot連接Microsoft SQL Server實現登錄驗證
這篇文章將非常系統(tǒng)地講解如何使用 Spring Boot 結合 Microsoft SQL Server 2019 完成一個完整的登錄驗證系統(tǒng),包括數據庫連接問題、SSL證書錯誤處理、CORS跨域詳細解釋和解決方案。
適合需要前后端聯調、單獨部署數據庫、獨立登錄服務的場景。
一、環(huán)境準備
- 開發(fā)工具:IDEA 2025.1
- Spring Boot 版本:3.4.3
- SQL Server 版本:Microsoft SQL Server 2019
- 瀏覽器:Chrome/Edge
技術選型
- Spring Boot Web
- JDBC 數據庫連接
- HTML + JavaScript 作為前端
項目結構建議
BoounionLoginBackend/ ├── src/ │ └── main/ │ ├── java/com/example/boounion/ │ │ ├── controller/LoginController.java │ │ ├── model/User.java │ │ ├── service/UserService.java │ │ └── BoounionLoginBackendApplication.java │ └── resources/ │ └── static/index.html │ └── application.properties ├── pom.xml
二、數據庫配置詳解(application.properties)
spring.datasource.url=jdbc:sqlserver://localhost:1433;databaseName=BoounionDB;encrypt=true;trustServerCertificate=true spring.datasource.username=sa spring.datasource.password=bl123456 spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver spring.jpa.hibernate.ddl-auto=none server.port=8080
重點解釋:
encrypt=true:SQL Server 2019 默認要求連接加密。如果不加,會連接失敗。trustServerCertificate=true:如果你沒有配置 SSL 證書,可以加上此參數,忽略證書校驗,避免出現PKIX path building failed錯誤。server.port=8080:設置后端啟動端口為8080,確保和前端訪問一致。
連接 SQL Server 常見錯誤總結:
| 錯誤提示 | 原因 | 解決方法 |
|---|---|---|
| TCP 1433端口連接失敗 | SQL Server未開啟TCP/IP | 配置SQL Server網絡協(xié)議,啟用TCP/IP |
| SSL 連接失敗 PKIX Error | 缺少受信任證書 | 配置 encrypt=true 且 trustServerCertificate=true |
| 登錄失敗 | 用戶名密碼錯誤 | 確認賬號密碼正確且允許SQL登錄 |
遇到的錯誤是典型的 SSL 證書驗證失敗,錯誤信息如下:
驅動程序無法通過使用 SSL 與 SQL Server 建立安全連接。
錯誤: PKIX path building failed: unable to find valid certification path
三、前端登錄界面(index.html)
頁面結構:
<input type="text" id="username" placeholder="用戶名"> <input type="password" id="password" placeholder="密碼"> <button onclick="login()">登錄</button>
美化 CSS 省略,重要的是 登錄函數邏輯。
登錄邏輯 JavaScript:
function login() {
const username = document.getElementById("username").value;
const password = document.getElementById("password").value;
fetch("/api/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ username, password })
})
.then(response => response.json().then(data => ({ status: response.status, body: data })))
.then(({ status, body }) => {
if (status === 200 && body.status === "success") {
window.location.href = body.redirectUrl;
} else {
alert(body.message || "登錄失敗");
}
})
.catch(() => alert("請求失敗,請檢查網絡"));
}
特點:
- 使用 fetch() 發(fā)送 POST 請求,提交 JSON 格式用戶名和密碼。
- 登錄成功后,前端通過 window.location.href 跳轉。
- 登錄失敗,使用 alert 彈窗提示用戶。
- 完全符合現代前后端分離開發(fā)方式。
四、后端登錄接口(LoginController.java)
核心邏輯:
@PostMapping("/login")
public ResponseEntity<Map<String, Object>> login(@RequestBody User user) {
String result = userService.login(user);
Map<String, Object> response = new HashMap<>();
switch (result) {
case "登錄成功":
response.put("status", "success");
response.put("redirectUrl", "https://www.baidu.com/s?wd=csdn");
return ResponseEntity.ok(response);
case "密碼錯誤":
response.put("status", "error");
response.put("message", "密碼錯誤");
return ResponseEntity.status(401).body(response);
case "用戶不存在":
response.put("status", "error");
response.put("message", "用戶不存在");
return ResponseEntity.status(404).body(response);
default:
response.put("status", "error");
response.put("message", "服務器異常");
return ResponseEntity.status(500).body(response);
}
}
亮點說明:
- 使用 Map 封裝返回 JSON,靈活可擴展。
- 成功返回 200 狀態(tài),帶 redirectUrl,由前端跳轉。
- 失敗返回具體的 401/404/500 狀態(tài)碼,便于前端判斷并提示。
? 保證登錄接口符合 RESTful API 設計規(guī)范。
五、數據庫驗證邏輯(UserService.java)
簡單查詢用戶密碼:
try (Connection conn = DriverManager.getConnection(dbUrl, dbUser, dbPassword)) {
String sql = "SELECT password FROM Users WHERE username = ?";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, user.getUsername());
try (ResultSet rs = stmt.executeQuery()) {
if (!rs.next()) return "用戶不存在";
if (!rs.getString("password").equals(user.getPassword())) return "密碼錯誤";
return "登錄成功";
}
}
} catch (SQLException e) {
e.printStackTrace();
return "數據庫錯誤";
}
安全設計要點:
- 使用 PreparedStatement,防止 SQL 注入攻擊。
- 明文密碼對比(后期建議增加加密如 BCrypt)。
- 連接和關閉資源使用 try-with-resources,避免泄漏。
六、跨域 CORS 問題詳細解決
現象
前端 fetch 請求接口時報錯:
Access to fetch at ‘http://localhost:8080/api/login’ from origin ‘http://localhost:5500’ has been blocked by CORS policy.

原因
瀏覽器安全策略,跨域請求被攔截。
完整解決方案:
1. 配置全局允許跨域
創(chuàng)建 WebConfig.java:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:5500")
.allowedMethods("GET", "POST")
.allowCredentials(true);
}
}
allowedOrigins指定你的前端地址(可以是 IP、本地域名)。allowedMethods指定支持的方法,如 POST、GET。allowCredentials(true)允許帶上 cookie(如果未來需要)。
2. 單接口上臨時添加 @CrossOrigin
如果你只想允許登錄接口跨域:
@CrossOrigin(origins = "http://localhost:5500")
@PostMapping("/login")
? 推薦使用全局配置統(tǒng)一處理,維護簡單。
七、總結
- 數據庫連接重點:SQL Server 需要
encrypt=true,如果無證書,加trustServerCertificate=true - 跨域問題重點:Spring Boot 后端必須添加 CORS 配置,否則前端 fetch 會被瀏覽器攔截。
- 前端處理重點:fetch 請求成功后由前端自己 window.location.href 跳轉。
- 后端接口規(guī)范:登錄接口返回 200狀態(tài)+JSON,而不是 302重定向。
- 安全建議:生產環(huán)境密碼應加密存儲,使用 BCrypt 算法。
附錄:完整文件(可自行補全代碼)
pom.xml ?
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>BoounionERP</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<!-- Spring Boot 父項目 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.3</version>
<relativePath/>
</parent>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- Spring Boot Web 模塊(包含內嵌 Tomcat) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 開發(fā)工具(自動重啟,非必須) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<!-- SQL Server JDBC 驅動 -->
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>11.2.3.jre11</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
index.html ?
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>登錄界面</title>
<style>
body {
font-family: Arial;
padding: 50px;
background-color: #f0f2f5;
}
.login-box {
background-color: white;
padding: 20px;
width: 300px;
margin: auto;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
input {
width: 100%;
margin-bottom: 10px;
padding: 8px;
box-sizing: border-box;
}
button {
width: 100%;
padding: 8px;
background-color: #4CAF50;
color: white;
border: none;
cursor: pointer;
}
</style>
</head>
<body>
<div class="login-box">
<h2>登錄</h2>
<input type="text" id="username" placeholder="用戶名">
<input type="password" id="password" placeholder="密碼">
<button onclick="login()">登錄</button>
</div>
<script>
function login() {
const username = document.getElementById("username").value;
const password = document.getElementById("password").value;
fetch("/api/login", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ username, password })
})
.then(response => response.json().then(data => ({ status: response.status, body: data })))
.then(({ status, body }) => {
if (status === 200 && body.status === "success") {
window.location.href = body.redirectUrl;
} else {
alert(body.message || "登錄失敗");
}
})
.catch(error => {
alert("請求失敗,請檢查網絡");
console.error(error);
});
}
</script>
</body>
</html>
application.properties ?
# 數據庫連接配置 spring.datasource.url=jdbc:sqlserver://localhost:1433;databaseName=BoounionDB;encrypt=true;trustServerCertificate=true spring.datasource.username=sa spring.datasource.password=bl123456 spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver # 其他常規(guī)配置 spring.jpa.hibernate.ddl-auto=none server.port=8080
Main.java ?
package org.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* ==================================================
* This class Main is responsible for [功能描述].
*
* @author darker
* @version 1.0
* ==================================================
*/
@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
User.java ?
package org.example.model;
/**
* ==================================================
* This class User is responsible for [功能描述].
*
* @author darker
* @version 1.0
* ==================================================
*/
public class User {
private String username;
private String password;
public User() {}
public User(String username, String password) {
this.username = username;
this.password = password;
}
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; }
}
UserService.java ?
package org.example.service;
import org.example.model.User;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.sql.*;
/**
* ==================================================
* This class UserService is responsible for [功能描述].
*
* @author darker
* @version 1.0
* ==================================================
*/
@Service
public class UserService {
@Value("${spring.datasource.url}")
private String dbUrl;
@Value("${spring.datasource.username}")
private String dbUser;
@Value("${spring.datasource.password}")
private String dbPassword;
public String login(User user) {
try (Connection conn = DriverManager.getConnection(dbUrl, dbUser, dbPassword)) {
String checkUserSql = "SELECT password FROM Users WHERE username = ?";
try (PreparedStatement stmt = conn.prepareStatement(checkUserSql)) {
stmt.setString(1, user.getUsername());
try (ResultSet rs = stmt.executeQuery()) {
if (!rs.next()) {
return "用戶不存在";
}
String dbPassword = rs.getString("password");
if (!dbPassword.equals(user.getPassword())) {
return "密碼錯誤";
}
return "登錄成功";
}
}
} catch (SQLException e) {
e.printStackTrace();
return "數據庫錯誤";
}
}
}
LoginController.java ?
package org.example.controller;
import org.example.model.User;
import org.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
/**
* ==================================================
* This class LoginController is responsible for [功能描述].
*
* @author darker
* @version 1.0
* ==================================================
*/
@RestController
@RequestMapping("/api")
public class LoginController {
@Autowired
private UserService userService;
@PostMapping("/login")
public ResponseEntity<Map<String, Object>> login(@RequestBody User user) {
String result = userService.login(user);
Map<String, Object> response = new HashMap<>();
switch (result) {
case "登錄成功":
// 拼接帶參數的跳轉地址
/*
String url = String.format(
"https://www.baidu.com/s?username=%s",
user.getUsername()
);
*/
String url = "https://www.baidu.com/s?wd=csdn";
response.put("status", "success");
response.put("redirectUrl", url);
return ResponseEntity.ok(response);
case "密碼錯誤":
response.put("status", "error");
response.put("message", "密碼錯誤");
return ResponseEntity.status(401).body(response);
case "用戶不存在":
response.put("status", "error");
response.put("message", "用戶不存在");
return ResponseEntity.status(404).body(response);
default:
response.put("status", "error");
response.put("message", "服務器異常");
return ResponseEntity.status(500).body(response);
}
}
}到此這篇關于SpringBoot連接Microsoft SQL Server實現登錄驗證的文章就介紹到這了,更多相關SpringBoot連SQL登錄驗證內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
ByteArrayOutputStream與InputStream互相轉換方式
這篇文章主要介紹了ByteArrayOutputStream與InputStream互相轉換方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12
springmvc 獲取@Requestbody轉換的異常處理方式
這篇文章主要介紹了springmvc 獲取@Requestbody轉換的異常處理方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07

