最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Security自定義用戶名密碼登錄頁(yè)面全過(guò)程

 更新時(shí)間:2026年06月12日 14:34:46   作者:知遠(yuǎn)漫談  
這篇文章主要介紹了Spring Security自定義用戶名密碼登錄頁(yè)面全過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

在現(xiàn)代 Web 應(yīng)用開(kāi)發(fā)中,安全性是不可忽視的重要環(huán)節(jié)。Spring Security 作為 Spring 生態(tài)中最成熟、最廣泛使用的安全框架,為開(kāi)發(fā)者提供了強(qiáng)大的認(rèn)證(Authentication)與授權(quán)(Authorization)能力。默認(rèn)情況下,Spring Security 會(huì)提供一個(gè)自動(dòng)生成的登錄頁(yè)面,但在實(shí)際項(xiàng)目中,我們幾乎總是需要根據(jù)業(yè)務(wù)需求和 UI/UX 設(shè)計(jì),定制屬于自己的登錄界面。

本文將深入探討如何在 Spring Boot 項(xiàng)目中使用 Spring Security 實(shí)現(xiàn)完全自定義的用戶名密碼登錄頁(yè)面。我們將從基礎(chǔ)配置開(kāi)始,逐步構(gòu)建一個(gè)完整的登錄流程,涵蓋表單設(shè)計(jì)、后端處理、錯(cuò)誤提示、記住我功能、CSRF 防護(hù)、登錄成功/失敗跳轉(zhuǎn)策略等核心內(nèi)容,并通過(guò)代碼示例和流程圖幫助你徹底掌握這一關(guān)鍵技能。

為什么需要自定義登錄頁(yè)面?

默認(rèn)的 Spring Security 登錄頁(yè)面雖然功能完整,但存在以下問(wèn)題:

  • 外觀簡(jiǎn)陋:無(wú)法匹配企業(yè)級(jí)應(yīng)用的 UI 風(fēng)格;
  • 響應(yīng)式缺失:不支持移動(dòng)端適配;
  • 多語(yǔ)言困難:難以集成國(guó)際化(i18n);
  • 擴(kuò)展性差:無(wú)法添加驗(yàn)證碼、第三方登錄等額外功能;
  • 安全細(xì)節(jié)暴露:默認(rèn)路徑和參數(shù)可能被攻擊者利用。

因此,自定義登錄頁(yè)面不僅是美觀需求,更是安全性和用戶體驗(yàn)的必要實(shí)踐。

小知識(shí):Spring Security 的默認(rèn)登錄頁(yè)面路徑是 /login,提交表單的 action 是 /login,用戶名字段為 username,密碼字段為 password。這些都可以被覆蓋。

項(xiàng)目初始化

我們使用 Spring Boot 3.x(基于 Jakarta EE 9+,使用 jakarta.* 包而非 javax.*)來(lái)搭建項(xiàng)目。確保你的開(kāi)發(fā)環(huán)境已安裝 JDK 17+ 和 Maven/Gradle。

依賴配置(Maven)

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity6</artifactId>
    </dependency>
</dependencies>

Thymeleaf 官方文檔 提供了與 Spring Security 集成的詳細(xì)說(shuō)明。

基礎(chǔ)安全配置

首先,我們需要禁用 Spring Security 的默認(rèn)登錄頁(yè)面,并指定我們自己的登錄頁(yè)面路徑。

創(chuàng)建 SecurityConfig 類

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authz -> authz
                .requestMatchers("/login", "/css/**", "/js/**", "/images/**").permitAll()
                .anyRequest().authenticated()
            )
            .formLogin(form -> form
                .loginPage("/login")          // 指定自定義登錄頁(yè)
                .loginProcessingUrl("/do-login") // 表單提交地址
                .usernameParameter("username")   // 用戶名參數(shù)名
                .passwordParameter("password")   // 密碼參數(shù)名
                .defaultSuccessUrl("/dashboard", true) // 登錄成功后跳轉(zhuǎn)
                .failureUrl("/login?error=true")     // 登錄失敗跳轉(zhuǎn)
                .permitAll()
            )
            .logout(logout -> logout
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login?logout=true")
                .permitAll()
            );

        return http.build();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails user = User.withDefaultPasswordEncoder()
            .username("admin")
            .password("123456")
            .roles("USER")
            .build();

        return new InMemoryUserDetailsManager(user);
    }
}

注意:User.withDefaultPasswordEncoder() 僅用于演示!生產(chǎn)環(huán)境必須使用強(qiáng)哈希算法(如 BCrypt)。

自定義登錄頁(yè)面(Thymeleaf)

我們?cè)?src/main/resources/templates 目錄下創(chuàng)建 login.html 文件。

login.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
    <meta charset="UTF-8">
    <title>用戶登錄</title>
    <link rel="stylesheet" th:href="@{/css/login.css}" rel="external nofollow" >
</head>
<body>
<div class="login-container">
    <h2>系統(tǒng)登錄</h2>
    <!-- 錯(cuò)誤信息提示 -->
    <div th:if="${param.error}" class="alert alert-error">
        用戶名或密碼錯(cuò)誤,請(qǐng)重試!
    </div>
    <!-- 成功登出提示 -->
    <div th:if="${param.logout}" class="alert alert-success">
        您已成功退出系統(tǒng)。
    </div>
    <form th:action="@{/do-login}" method="post">
        <!-- CSRF Token 自動(dòng)注入 -->
        <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
        <div class="form-group">
            <label for="username">用戶名</label>
            <input type="text" id="username" name="username" required autofocus/>
        </div>
        <div class="form-group">
            <label for="password">密碼</label>
            <input type="password" id="password" name="password" required/>
        </div>
        <div class="form-group remember-me">
            <input type="checkbox" id="remember-me" name="remember-me"/>
            <label for="remember-me">記住我</label>
        </div>
        <button type="submit">登錄</button>
    </form>
</div>
</body>
</html>

關(guān)鍵點(diǎn)說(shuō)明

  • th:action="@{/do-login}":表單提交到 /do-login,與 loginProcessingUrl 一致;
  • CSRF Token 通過(guò) Thymeleaf 自動(dòng)注入,防止跨站請(qǐng)求偽造;
  • name="remember-me" 是 Spring Security “記住我”功能的默認(rèn)參數(shù)名;
  • 使用 param.errorparam.logout 獲取 URL 參數(shù)以顯示提示。

靜態(tài)資源處理

為了讓登錄頁(yè)面樣式正常加載,需在 SecurityConfig 中放行靜態(tài)資源路徑:

.requestMatchers("/login", "/css/**", "/js/**", "/images/**", "/favicon.ico").permitAll()

并在 src/main/resources/static/css 下創(chuàng)建 login.css

body {
    font-family: Arial, sans-serif;
    background-color: #f4f4f4;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
}
.login-container {
    background: white;
    padding: 2rem;
    border-radius: 8px;
    box-shadow: 0 0 10px rgba(0,0,0,0.1);
    width: 300px;
}
.form-group {
    margin-bottom: 1rem;
}
.form-group label {
    display: block;
    margin-bottom: 0.5rem;
}
.form-group input {
    width: 100%;
    padding: 0.5rem;
    border: 1px solid #ccc;
    border-radius: 4px;
    box-sizing: border-box;
}
.remember-me {
    display: flex;
    align-items: center;
}
.remember-me input[type="checkbox"] {
    margin-right: 0.5rem;
}
button {
    width: 100%;
    padding: 0.75rem;
    background-color: #007bff;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}
button:hover {
    background-color: #0056b3;
}
.alert {
    padding: 0.75rem;
    margin-bottom: 1rem;
    border-radius: 4px;
}
.alert-error {
    background-color: #f8d7da;
    color: #721c24;
}
.alert-success {
    background-color: #d4edda;
    color: #155724;
}

登錄流程解析

理解 Spring Security 的登錄流程對(duì)調(diào)試和擴(kuò)展至關(guān)重要。

關(guān)鍵組件說(shuō)明

  • UsernamePasswordAuthenticationFilter:負(fù)責(zé)攔截 /do-login 請(qǐng)求;
  • UserDetailsService:加載用戶信息(可對(duì)接數(shù)據(jù)庫(kù));
  • AuthenticationProvider:驗(yàn)證密碼是否匹配;
  • 成功/失敗處理器決定跳轉(zhuǎn)邏輯。

實(shí)現(xiàn)數(shù)據(jù)庫(kù)用戶認(rèn)證

前面我們使用了內(nèi)存用戶,現(xiàn)在將其替換為數(shù)據(jù)庫(kù)查詢。

1. 添加 JPA 依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

2. 創(chuàng)建 User 實(shí)體

import jakarta.persistence.*;

@Entity
@Table(name = "users")
public class AppUser {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true, nullable = false)
    private String username;

    @Column(nullable = false)
    private String password;

    @Column(nullable = false)
    private boolean enabled = true;

    // getters and setters
}

3. 創(chuàng)建 UserRepository

import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<AppUser, Long> {
    AppUser findByUsername(String username);
}

4. 自定義 UserDetailsService

import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

@Service
public class CustomUserDetailsService implements UserDetailsService {

    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;

    public CustomUserDetailsService(UserRepository userRepository, PasswordEncoder passwordEncoder) {
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        AppUser user = userRepository.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("用戶不存在: " + username);
        }

        return org.springframework.security.core.userdetails.User.builder()
            .username(user.getUsername())
            .password(user.getPassword()) // 已加密
            .authorities("ROLE_USER")
            .accountExpired(false)
            .accountLocked(false)
            .credentialsExpired(false)
            .disabled(!user.isEnabled())
            .build();
    }
}

5. 更新 SecurityConfig

移除 userDetailsService() 方法,注入 CustomUserDetailsService

@Autowired
private CustomUserDetailsService customUserDetailsService;

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    // ... 其他配置不變
    http.userDetailsService(customUserDetailsService);
    return http.build();
}

6. 密碼編碼器配置

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

安全建議:永遠(yuǎn)不要存儲(chǔ)明文密碼!BCrypt 是目前推薦的密碼哈希算法。

處理登錄成功與失敗

Spring Security 允許我們自定義登錄成功和失敗的行為,而不僅僅是跳轉(zhuǎn)。

自定義成功處理器

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request,
                                        HttpServletResponse response,
                                        Authentication authentication) throws IOException, ServletException {
        // 可記錄日志、更新最后登錄時(shí)間等
        System.out.println("用戶 " + authentication.getName() + " 登錄成功");

        // 默認(rèn)跳轉(zhuǎn)
        response.sendRedirect("/dashboard");
    }
}

自定義失敗處理器

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {

    @Override
    public void onAuthenticationFailure(HttpServletRequest request,
                                        HttpServletResponse response,
                                        AuthenticationException exception) throws IOException, ServletException {
        System.out.println("登錄失敗: " + exception.getMessage());

        // 可記錄失敗次數(shù)、鎖定賬戶等
        response.sendRedirect("/login?error=" + exception.getClass().getSimpleName());
    }
}

在 SecurityConfig 中注冊(cè)

@Autowired
private CustomAuthenticationSuccessHandler successHandler;

@Autowired
private CustomAuthenticationFailureHandler failureHandler;

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .formLogin(form -> form
            .loginPage("/login")
            .loginProcessingUrl("/do-login")
            .successHandler(successHandler)
            .failureHandler(failureHandler)
            .permitAll()
        );
    // ...
}

應(yīng)用場(chǎng)景

  • 成功時(shí)記錄 IP、設(shè)備信息;
  • 失敗時(shí)限制嘗試次數(shù),防止暴力.破 解;
  • 根據(jù)角色跳轉(zhuǎn)不同首頁(yè)。

“記住我”功能實(shí)現(xiàn)

“記住我”允許用戶在關(guān)閉瀏覽器后仍保持登錄狀態(tài)(通常通過(guò)持久化 Cookie 實(shí)現(xiàn))。

1. 數(shù)據(jù)庫(kù)表結(jié)構(gòu)

CREATE TABLE persistent_logins (
    username VARCHAR(64) NOT NULL,
    series VARCHAR(64) PRIMARY KEY,
    token VARCHAR(64) NOT NULL,
    last_used TIMESTAMP NOT NULL
);

2. 配置 RememberMeServices

@Bean
public PersistentTokenRepository persistentTokenRepository() {
    JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
    tokenRepository.setDataSource(dataSource);
    // 自動(dòng)建表(僅首次)
    // tokenRepository.setCreateTableOnStartup(true);
    return tokenRepository;
}

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .rememberMe(remember -> remember
            .key("myAppKey") // 必須設(shè)置,用于加密
            .tokenRepository(persistentTokenRepository())
            .tokenValiditySeconds(7 * 24 * 3600) // 7天
            .userDetailsService(customUserDetailsService)
        );
    // ...
}

原理:登錄時(shí)勾選“記住我”,服務(wù)器生成 seriestoken 存入數(shù)據(jù)庫(kù),并設(shè)置 Cookie。下次訪問(wèn)時(shí),通過(guò) Cookie 中的憑證自動(dòng)登錄。

CSRF 防護(hù)與自定義表單

Spring Security 默認(rèn)啟用 CSRF(跨站請(qǐng)求偽造)防護(hù),要求每個(gè)修改狀態(tài)的請(qǐng)求(POST/PUT/DELETE)攜帶有效的 CSRF Token。

在 Thymeleaf 表單中,我們通過(guò)以下方式自動(dòng)注入:

<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>

如果你使用的是純 HTML 或 AJAX,需手動(dòng)處理:

AJAX 示例(JavaScript)

// 從 meta 標(biāo)簽獲取 CSRF Token
var csrfToken = document.querySelector("meta[name='_csrf']").getAttribute("content");
var csrfHeader = document.querySelector("meta[name='_csrf_header']").getAttribute("content");
// 發(fā)送請(qǐng)求時(shí)添加 Header
fetch('/do-login', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        [csrfHeader]: csrfToken
    },
    body: 'username=admin&password=123456'
});

對(duì)應(yīng)的 HTML 需添加:

<meta name="_csrf" th:content="${_csrf.token}"/>
<meta name="_csrf_header" th:content="${_csrf.headerName}"/>

重要:不要禁用 CSRF!除非你明確知道自己在做什么(如 REST API 使用 JWT)。

國(guó)際化(i18n)支持

為了讓登錄頁(yè)面支持多語(yǔ)言,我們可以集成 Spring 的 MessageSource。

1. 創(chuàng)建 messages.properties

# src/main/resources/messages.properties
login.title=用戶登錄
login.username=用戶名
login.password=密碼
login.remember=記住我
login.button=登錄
error.bad.credentials=用戶名或密碼錯(cuò)誤

2. messages_zh_CN.properties

login.title=用戶登錄
login.username=用戶名
login.password=密碼
login.remember=記住我
login.button=登錄
error.bad.credentials=用戶名或密碼錯(cuò)誤

3. 在 Thymeleaf 中使用

<h2 th:text="#{login.title}">用戶登錄</h2>
<label for="username" th:text="#{login.username}">用戶名</label>
<!-- 其他類似 -->
<div th:if="${param.error}" class="alert alert-error" th:text="#{error.bad.credentials}"></div>

4. 配置 LocaleResolver

@Bean
public LocaleResolver localeResolver() {
    AcceptHeaderLocaleResolver resolver = new AcceptHeaderLocaleResolver();
    resolver.setDefaultLocale(Locale.CHINA);
    return resolver;
}

提示:瀏覽器通過(guò) Accept-Language 頭自動(dòng)選擇語(yǔ)言。

登錄驗(yàn)證碼集成(可選)

雖然 Spring Security 本身不提供驗(yàn)證碼,但我們可以輕松集成。

1. 添加 Kaptcha 依賴(示例)

<dependency>
    <groupId>com.github.penggle</groupId>
    <artifactId>kaptcha</artifactId>
    <version>2.3.2</version>
</dependency>

2. 配置 Kaptcha

@Bean
public DefaultKaptcha kaptcha() {
    DefaultKaptcha kaptcha = new DefaultKaptcha();
    Properties props = new Properties();
    props.setProperty("kaptcha.border", "no");
    props.setProperty("kaptcha.textproducer.font.color", "black");
    props.setProperty("kaptcha.textproducer.char.space", "10");
    kaptcha.setConfig(new Config(props));
    return kaptcha;
}

3. 驗(yàn)證碼 Controller

@GetMapping("/captcha")
public void captcha(HttpServletRequest request, HttpServletResponse response) throws IOException {
    response.setContentType("image/jpeg");
    String capText = kaptcha.createText();
    request.getSession().setAttribute("captcha", capText);
    BufferedImage image = kaptcha.createImage(capText);
    ImageIO.write(image, "jpg", response.getOutputStream());
}

4. 修改登錄表單

<img th:src="@{/captcha}" onclick="this.src='/captcha?' + Math.random()" alt="驗(yàn)證碼"/>
<input type="text" name="captcha" placeholder="請(qǐng)輸入驗(yàn)證碼" required/>

5. 自定義 AuthenticationFilter

繼承 UsernamePasswordAuthenticationFilter,在 attemptAuthentication 中校驗(yàn)驗(yàn)證碼。

注意:驗(yàn)證碼校驗(yàn)應(yīng)在密碼校驗(yàn)之前,避免無(wú)效請(qǐng)求消耗資源。

常見(jiàn)問(wèn)題與調(diào)試技巧

1. 登錄后無(wú)限重定向

原因:defaultSuccessUrl 指向的頁(yè)面未放行,導(dǎo)致再次跳轉(zhuǎn)到登錄頁(yè)。

? 解決:確保 /dashboardauthenticated() 保護(hù),且用戶有權(quán)限訪問(wèn)。

2. CSRF Token 無(wú)效

現(xiàn)象:提交表單報(bào) 403 Forbidden。

? 檢查:

  • 表單是否包含 <input type="hidden" th:name="${_csrf.parameterName}" ... />
  • 是否使用了正確的 POST 方法;
  • Session 是否過(guò)期(Token 綁定 Session)。

3. 密碼不匹配

? 檢查:

  • 數(shù)據(jù)庫(kù)存儲(chǔ)的密碼是否經(jīng)過(guò) BCrypt 加密;
  • PasswordEncoder 是否與加密時(shí)一致;
  • 不要使用 User.withDefaultPasswordEncoder()

4. 日志調(diào)試

application.properties 中開(kāi)啟安全日志:

logging.level.org.springframework.security=DEBUG

安全最佳實(shí)踐

強(qiáng)制 HTTPS:生產(chǎn)環(huán)境務(wù)必使用 HTTPS,防止密碼嗅探。

http.requiresChannel(channel -> channel.anyRequest().requiresSecure());
  1. 密碼策略:前端+后端雙重校驗(yàn)(長(zhǎng)度、復(fù)雜度)。

  2. 賬戶鎖定:多次失敗后臨時(shí)鎖定(可通過(guò) DaoAuthenticationProvider 擴(kuò)展)。

Session 管理

http.sessionManagement(session -> session
    .maximumSessions(1)
    .expiredUrl("/login?expired=true")
);

安全頭設(shè)置

http.headers(headers -> headers
    .frameOptions().deny()
    .contentTypeOptions().and()
    .xssProtection().and()
    .cacheControl()
);

OWASP Top 10 是 Web 安全的權(quán)威指南,值得每位開(kāi)發(fā)者閱讀。

總結(jié)

通過(guò)本文,我們系統(tǒng)地學(xué)習(xí)了如何在 Spring Security 中實(shí)現(xiàn)完全自定義的用戶名密碼登錄頁(yè)面。從基礎(chǔ)配置、頁(yè)面設(shè)計(jì)、數(shù)據(jù)庫(kù)集成,到高級(jí)功能如“記住我”、CSRF 防護(hù)、國(guó)際化和驗(yàn)證碼,每一步都配有可運(yùn)行的代碼示例。

自定義登錄頁(yè)面不僅是 UI 的替換,更是安全架構(gòu)的重要組成部分。合理的錯(cuò)誤處理、日志記錄、會(huì)話管理和輸入驗(yàn)證,能顯著提升應(yīng)用的安全性與用戶體驗(yàn)。

記?。?strong>安全不是功能,而是持續(xù)的過(guò)程。隨著業(yè)務(wù)發(fā)展,不斷審視和加固你的認(rèn)證機(jī)制,才能抵御日益復(fù)雜的網(wǎng)絡(luò)威脅。

下一步建議

  • 集成 OAuth2 / 微信登錄;
  • 實(shí)現(xiàn)多因素認(rèn)證(MFA);
  • 使用 JWT 替代表單登錄(適用于前后端分離)。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • springboot整合通用Mapper簡(jiǎn)化單表操作詳解

    springboot整合通用Mapper簡(jiǎn)化單表操作詳解

    這篇文章主要介紹了springboot整合通用Mapper簡(jiǎn)化單表操作,通用Mapper是一個(gè)基于Mybatis,將單表的增刪改查通過(guò)通用方法實(shí)現(xiàn),來(lái)減少SQL編寫的開(kāi)源框架,需要的朋友可以參考下
    2019-06-06
  • Java注解的簡(jiǎn)單入門小案例

    Java注解的簡(jiǎn)單入門小案例

    這篇文章主要介紹了Java注解的簡(jiǎn)單入門小案例,注解是干什么的?怎么使用?注解的簡(jiǎn)單用法,需要的朋友可以參考下
    2023-04-04
  • 使用原生JDBC動(dòng)態(tài)解析并獲取表格列名和數(shù)據(jù)的方法

    使用原生JDBC動(dòng)態(tài)解析并獲取表格列名和數(shù)據(jù)的方法

    這篇文章主要介紹了使用原生JDBC動(dòng)態(tài)解析并獲取表格列名和數(shù)據(jù),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-08-08
  • 詳解使用spring cloud config來(lái)統(tǒng)一管理配置文件

    詳解使用spring cloud config來(lái)統(tǒng)一管理配置文件

    這篇文章主要介紹了詳解使用spring cloud config來(lái)統(tǒng)一管理配置文件,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-12-12
  • Java中工具Jstack的使用實(shí)例

    Java中工具Jstack的使用實(shí)例

    jstack用于生成java虛擬機(jī)當(dāng)前時(shí)刻的線程快照,下面這篇文章主要給大家介紹了關(guān)于Java中工具Jstack使用的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-04-04
  • Quarkus的Spring擴(kuò)展快速改造Spring項(xiàng)目

    Quarkus的Spring擴(kuò)展快速改造Spring項(xiàng)目

    這篇文章主要為大家介紹了Quarkus的Spring項(xiàng)目擴(kuò)展,帶大家快速改造Spring項(xiàng)目示例演繹,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-02-02
  • Java解析照片拿到GPS位置數(shù)據(jù)的詳細(xì)步驟

    Java解析照片拿到GPS位置數(shù)據(jù)的詳細(xì)步驟

    這篇文章主要介紹了Java解析照片拿到GPS位置數(shù)據(jù),本文給大家介紹代碼環(huán)境及核心代碼,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03
  • java 裝飾模式(Decorator Pattern)詳解

    java 裝飾模式(Decorator Pattern)詳解

    這篇文章主要介紹了java 裝飾模式(Decorator Pattern)詳解的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • Java?Bean?Validation使用示例詳解

    Java?Bean?Validation使用示例詳解

    這篇文章主要為大家介紹了Java?Bean?Validation的使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • 基于springioc bean 的幾個(gè)屬性介紹

    基于springioc bean 的幾個(gè)屬性介紹

    下面小編就為大家?guī)?lái)一篇基于springioc bean 的幾個(gè)屬性介紹。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就想給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-09-09

最新評(píng)論

平度市| 利川市| 长丰县| 南城县| 清河县| 文山县| 石首市| 高尔夫| 仪陇县| 瑞安市| 班玛县| 湖北省| 博客| 通山县| 英超| 醴陵市| 商洛市| 汝南县| 岐山县| 通州市| 古丈县| 紫阳县| 曲周县| 新建县| 翁源县| 剑河县| 通渭县| 泊头市| 延寿县| 监利县| 新泰市| 双桥区| 桃园市| 香港 | 岳西县| 同德县| 英超| 隆尧县| 临猗县| 凤山市| 阿克陶县|