SpringSecurity入门

文章目录

SpringSecurity入门

一、引言

在Java Web后端开发中,安全是一个不可忽视的重要部分。Spring Security是一个功能强大且可高度定制的身份验证和访问控制框架,它集成了Spring生态,提供了认证(Authentication)和授权(Authorization)的功能。本文将带你走进Spring Security的世界,从基础入门到实际应用,帮助你掌握Spring Security的核心概念和使用方式。

二、快速入门

1、环境搭建

首先,我们需要搭建一个Spring Boot项目,并引入Spring Security依赖。

1.1、添加依赖

pom.xml中添加以下依赖:

xml 复制代码
<dependencies>
    <!-- Spring Boot Web Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Spring Security Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <!-- Lombok for reducing boilerplate code -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>
1.2、创建启动类

创建一个Spring Boot启动类:

java 复制代码
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SecurityApplication {
    public static void main(String[] args) {
        SpringApplication.run(SecurityApplication.class, args);
    }
}
1.3、创建Controller

创建一个简单的Controller来测试:

java 复制代码
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello() {
        return "Hello, Spring Security!";
    }
}

2、Spring Security配置

接下来,我们需要配置Spring Security。

2.1、配置SecurityConfig

创建一个配置类SecurityConfig,继承自WebSecurityConfigurerAdapter

java 复制代码
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .anyRequest().authenticated()
            .and()
            .formLogin()
                .loginPage("/login").permitAll()
            .and()
            .logout()
                .permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
            .withUser("user").password("{noop}password").roles("USER");
    }
}

在这个配置中,我们启用了Spring Security,并配置了所有的请求都需要认证。同时,我们定义了一个内存中的用户认证信息。

三、深入理解

1、认证和授权

Spring Security的核心在于认证和授权。

1.1、认证(Authentication)

认证是确认用户身份的过程。在Spring Security中,这通常是通过UserDetailsService接口实现的,它允许我们从数据库或其他服务中加载用户的认证信息。

java 复制代码
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;

import java.util.Collections;

@Service
public class CustomUserDetailsService implements UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 模拟从数据库中获取用户信息
        if ("user".equals(username)) {
            return new User("user", "password", Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")));
        }
        throw new UsernameNotFoundException("User not found");
    }
}

在上述代码中,我们创建了一个CustomUserDetailsService类,它实现了UserDetailsService接口。loadUserByUsername方法用于根据用户名加载用户信息。如果用户存在,则创建一个UserDetails对象并返回;如果用户不存在,则抛出UsernameNotFoundException异常。

1.2、授权(Authorization)

授权是确定用户是否有权限执行特定操作的过程。Spring Security提供了多种方式来定义和检查权限,包括注解、表达式语言等。

使用注解进行权限控制:

java 复制代码
import org.springframework.security.access.prepost.PreAuthorize;

@RestController
public class SecureController {

    @PreAuthorize("hasAuthority('ROLE_ADMIN')")
    @GetMapping("/secure/admin")
    public String adminEndpoint() {
        return "Admin endpoint";
    }

    @PreAuthorize("hasAnyAuthority('ROLE_USER', 'ROLE_ADMIN')")
    @GetMapping("/secure/user")
    public String userEndpoint() {
        return "User endpoint";
    }
}

在上述代码中,我们使用了@PreAuthorize注解来控制对/secure/admin/secure/user两个端点的访问。hasAuthority函数用于检查用户是否具有特定的权限。

2、自定义认证

在实际应用中,我们可能需要自定义认证逻辑,比如使用JWT。

2.1、JWT认证

创建一个JWT工具类,用于生成和解析JWT:

java 复制代码
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

public class JwtUtil {

    private String secretKey = "secret";

    public String generateToken(String username) {
        return Jwts.builder()
            .setSubject(username)
            .signWith(SignatureAlgorithm.HS512, secretKey)
            .compact();
    }

    public String extractUsername(String token) {
        return extractClaim(token, Claims::getSubject);
    }

    public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = extractAllClaims(token).getBody();
        return claimsResolver.apply(claims);
    }

    private Claims extractAllClaims(String token) {
        return Jwts.parser()
            .setSigningKey(secretKey)
            .parseClaimsJws(token)
            .getBody();
    }
}

在上述代码中,我们创建了一个JwtUtil类,它提供了生成JWT和解析JWT的方法。generateToken方法用于生成一个JWT,extractUsername方法用于从JWT中提取用户名。

2.2、自定义认证过滤器

创建一个自定义认证过滤器,用于处理JWT认证:

java 复制代码
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JwtUtil jwtUtil;

    public JwtAuthenticationFilter(JwtUtil jwtUtil) {
        this.jwtUtil = jwtUtil;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String token = request.getHeader("Authorization");
        if (token != null && token.startsWith("Bearer ")) {
            String username = jwtUtil.extractUsername(token.substring(7));
            if (username != null) {
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }
        filterChain.doFilter(request, response);
    }
}

在上述代码中,我们创建了一个JwtAuthenticationFilter类,它继承自OncePerRequestFilterdoFilterInternal方法用于处理JWT认证。如果请求头中包含JWT,则从JWT中提取用户名,并创建一个UsernamePasswordAuthenticationToken对象,将其设置到SecurityContextHolder中。

四、总结

通过本文的介绍,你应该对Spring Security有了基本的了解。从快速入门到深入理解,再到自定义认证,Spring Security提供了强大的安全性支持,可以帮助我们构建安全的Web应用。希望本文能够帮助你快速上手Spring Security,并在你的项目中发挥作用。


版权声明:本博客内容为原创,转载请保留原文链接及作者信息。

参考文章

相关推荐
Vitalia30 分钟前
从零开始学 Rust:基本概念——变量、数据类型、函数、控制流
开发语言·后端·rust
猎人everest3 小时前
SpringBoot应用开发入门
java·spring boot·后端
孤雪心殇9 小时前
简单易懂,解析Go语言中的Map
开发语言·数据结构·后端·golang·go
White graces9 小时前
正则表达式效验邮箱格式, 手机号格式, 密码长度
前端·spring boot·spring·正则表达式·java-ee·maven·intellij-idea
是姜姜啊!10 小时前
redis的应用,缓存,分布式锁
java·redis·spring
小突突突10 小时前
模拟实现Java中的计时器
java·开发语言·后端·java-ee
web1376560764310 小时前
Scala的宝藏库:探索常用的第三方库及其应用
开发语言·后端·scala
闲猫11 小时前
go 反射 interface{} 判断类型 获取值 设置值 指针才可以设置值
开发语言·后端·golang·反射
奋斗的袍子00711 小时前
Spring AI + Ollama 实现调用DeepSeek-R1模型API
人工智能·spring boot·深度学习·spring·springai·deepseek
LUCIAZZZ12 小时前
EasyExcel快速入门
java·数据库·后端·mysql·spring·spring cloud·easyexcel