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,并在你的项目中发挥作用。


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

参考文章

相关推荐
Pandaconda16 分钟前
【Golang 面试题】每日 3 题(三十九)
开发语言·经验分享·笔记·后端·面试·golang·go
荆州克莱24 分钟前
Golang的图形编程基础
spring boot·spring·spring cloud·css3·技术
m0_7482350735 分钟前
springboot中配置logback-spring.xml
spring boot·spring·logback
编程小筑1 小时前
R语言的编程范式
开发语言·后端·golang
技术的探险家1 小时前
Elixir语言的文件操作
开发语言·后端·golang
ss2731 小时前
【2025小年源码免费送】
前端·后端
Ai 编码助手1 小时前
Golang 中强大的重试机制,解决瞬态错误
开发语言·后端·golang
蒙双眼看世界1 小时前
IDEA运行Java项目总会报程序包xxx不存在
java·spring·maven
齐雅彤2 小时前
Lisp语言的区块链
开发语言·后端·golang
齐雅彤2 小时前
Lisp语言的循环实现
开发语言·后端·golang