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


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

参考文章

相关推荐
代码小鑫18 分钟前
A032-基于Spring Boot的健康医院门诊在线挂号系统
java·开发语言·spring boot·后端·spring·毕业设计
豌豆花下猫35 分钟前
REST API 已经 25 岁了:它是如何形成的,将来可能会怎样?
后端·python·ai
喔喔咿哈哈1 小时前
【手撕 Spring】 -- Bean 的创建以及获取
java·后端·spring·面试·开源·github
码农小丘1 小时前
了解springboot国际化用途以及使用
java·spring boot·spring
tian-ming1 小时前
JavaWeb后端开发知识储备1
java·spring boot·nginx·spring·maven
夏微凉.1 小时前
【JavaEE进阶】Spring AOP 原理
java·spring boot·后端·spring·java-ee·maven
杨过姑父1 小时前
org.springframework.context.support.ApplicationListenerDetector 详细介绍
java·前端·spring
理想不理想v1 小时前
使用JS实现文件流转换excel?
java·前端·javascript·css·vue.js·spring·面试
抱走江江1 小时前
SpringCloud框架学习(第二部分:Consul、LoadBalancer和openFeign)
学习·spring·spring cloud
不会编程的懒洋洋2 小时前
Spring Cloud Eureka 服务注册与发现
java·笔记·后端·学习·spring·spring cloud·eureka