前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Security 简单使用教程

Spring Security 简单使用教程

原创
作者头像
繁依Fanyi
发布2024-06-17 21:13:49
1010
发布2024-06-17 21:13:49

Spring Security 是一个强大的、安全性框架,用于保护 Spring 应用程序。本文将详细介绍如何在一个 Spring Boot 项目中使用 Spring Security,从基础配置到自定义安全需求。

创建 Spring Boot 项目

首先,我们需要创建一个 Spring Boot 项目。可以通过 Spring Initializr 快速生成项目。

  1. 访问 Spring Initializr.
  2. 选择如下选项:
    • Project: Gradle Project 或 Maven Project
    • Language: Java
    • Spring Boot: 最新稳定版本
  3. 添加依赖:
    • Spring Web
    • Spring Security
    • Spring Data JPA(用于后续数据库操作)
    • H2 Database(用于演示)

生成并下载项目,解压后使用你喜欢的 IDE(如 IntelliJ IDEA 或 Eclipse)打开。

引入 Spring Security 依赖

如果你通过 Spring Initializr 创建了项目,Spring Security 依赖应该已经包括在内。如果没有,可以手动添加依赖:

Maven:

代码语言:xml
复制
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

Gradle:

代码语言:groovy
复制
implementation 'org.springframework.boot:spring-boot-starter-security'

默认配置和基本认证

Spring Security 默认提供了基本的 HTTP Basic 认证。启动项目后,访问任意端点,你会被要求输入用户名和密码。

默认情况下,Spring Boot 会生成一个随机密码并打印在控制台。默认用户名是 user

代码语言:plaintext
复制
Using generated security password: <generated-password>

自定义用户认证

让我们创建一个自定义的用户认证。首先,创建一个配置类来扩展 WebSecurityConfigurerAdapter

代码语言:java
复制
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    @Override
    protected UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withDefaultPasswordEncoder()
                .username("user")
                .password("password")
                .roles("USER")
                .build());
        manager.createUser(User.withDefaultPasswordEncoder()
                .username("admin")
                .password("admin")
                .roles("ADMIN")
                .build());
        return manager;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .antMatchers("/user/**").hasRole("USER")
                .antMatchers("/", "/home").permitAll()
                .and()
                .formLogin();
    }
}

基于数据库的用户认证

接下来,配置基于数据库的用户认证。首先,创建用户实体类和数据库表。

User 实体类:

代码语言:java
复制
import javax.persistence.*;

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String password;
    private String role;

    // getters and setters
}

UserRepository 接口:

代码语言:java
复制
import org.springframework.data.jpa.repository.JpaRepository;

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

数据库初始化脚本:

src/main/resources 目录下创建 data.sql 文件,初始化一些数据。

代码语言:sql
复制
INSERT INTO user (username, password, role) VALUES ('user', 'password', 'ROLE_USER');
INSERT INTO user (username, password, role) VALUES ('admin', 'admin', 'ROLE_ADMIN');

SecurityConfig 配置:

代码语言:java
复制
import org.springframework.beans.factory.annotation.Autowired;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserRepository userRepository;

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

    @Override
    protected UserDetailsService userDetailsService() {
        return username -> {
            User user = userRepository.findByUsername(username);
            if (user == null) {
                throw new UsernameNotFoundException("User not found");
            }
            return org.springframework.security.core.userdetails.User
                    .withUsername(user.getUsername())
                    .password(passwordEncoder().encode(user.getPassword()))
                    .roles(user.getRole())
                    .build();
        };
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .antMatchers("/user/**").hasRole("USER")
                .antMatchers("/", "/home").permitAll()
                .and()
                .formLogin();
    }
}

自定义登录页面

创建一个自定义的登录页面。首先,在 src/main/resources/templates 目录下创建一个 login.html 文件。

代码语言:html
复制
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Login</title>
</head>
<body>
<h1>Login</h1>
<form th:action="@{/login}" method="post">
    <div>
        <label>Username:</label>
        <input type="text" name="username"/>
    </div>
    <div>
        <label>Password:</label>
        <input type="password" name="password"/>
    </div>
    <div>
        <button type="submit">Login</button>
    </div>
</form>
</body>
</html>

然后,在 SecurityConfig 中配置自定义登录页面。

代码语言:java
复制
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .antMatchers("/admin/**").hasRole("ADMIN")
            .antMatchers("/user/**").hasRole("USER")
            .antMatchers("/", "/home").permitAll()
            .and()
            .formLogin()
            .loginPage("/login")
            .permitAll();
}

方法级别的安全性

Spring Security 还支持方法级别的安全性。我们可以在服务层使用注解来保护方法。

首先,启用全局方法安全性。在主应用程序类中添加 @EnableGlobalMethodSecurity(prePostEnabled = true) 注解。

代码语言:java
复制
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;

@SpringBootApplication
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

然后,在服务层方法上使用 @PreAuthorize 注解。

代码语言:java
复制
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @PreAuthorize("hasRole('ROLE_ADMIN')")
    public void adminMethod() {
        // admin only logic
    }

    @PreAuthorize("hasRole('ROLE_USER')")
    public void userMethod() {
        // user only logic
    }
}

处理跨站请求伪造(CSRF)

Spring Security 默认启用了 CSRF 保护。在开发和测试过程中,我们可能需要禁用它。在 SecurityConfig 中进行配置。

代码语言:java
复制
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
            .authorizeRequests()
            .antMatchers("/admin/**").hasRole("ADMIN")
            .antMatchers("/user/**").hasRole("USER")
            .antMatchers("/", "/home").permitAll()
            .and()
            .formLogin()
            .loginPage("/login")
            .permitAll();
}

日志记录和异常处理

我们可以通过自定义 AuthenticationEntryPointAccessDeniedHandler 来处理认证和授权异常。

代码语言:java
复制
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;


import org.springframework.security.web.access.AccessDeniedHandlerImpl;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
    }
}

@Component
public class CustomAccessDeniedHandler extends AccessDeniedHandlerImpl {

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {
        response.sendError(HttpServletResponse.SC_FORBIDDEN, "Forbidden");
    }
}

SecurityConfig 中配置这些组件。

代码语言:java
复制
@Autowired
private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;

@Autowired
private CustomAccessDeniedHandler customAccessDeniedHandler;

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
            .authorizeRequests()
            .antMatchers("/admin/**").hasRole("ADMIN")
            .antMatchers("/user/**").hasRole("USER")
            .antMatchers("/", "/home").permitAll()
            .and()
            .formLogin()
            .loginPage("/login")
            .permitAll()
            .and()
            .exceptionHandling()
            .authenticationEntryPoint(customAuthenticationEntryPoint)
            .accessDeniedHandler(customAccessDeniedHandler);
}

总结

通过这篇详细的教程,我们已经学习了如何在 Spring Boot 项目中集成 Spring Security,包括基本配置、自定义用户认证、基于数据库的用户认证、自定义登录页面、方法级别的安全性、CSRF 保护以及日志记录和异常处理。Spring Security 提供了强大的功能和灵活的配置选项,使我们能够根据需求来保护应用程序的安全。


我正在参与2024腾讯技术创作特训营最新征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 创建 Spring Boot 项目
  • 引入 Spring Security 依赖
  • 默认配置和基本认证
  • 自定义用户认证
  • 基于数据库的用户认证
  • 自定义登录页面
  • 方法级别的安全性
  • 处理跨站请求伪造(CSRF)
  • 日志记录和异常处理
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档