SpringSecurity详解整合JWT实现全过程

yizhihongxing

SpringSecurity详解整合JWT实现全过程

介绍

本文将详细讲解如何使用Spring Security和JWT实现基于token的用户身份认证和授权管理,帮助开发者更好地理解和使用Spring Security,同时提高安全性能和开发效率。

知识储备

在阅读本文之前,请确保你已经熟悉以下内容:

  1. Spring框架,特别是Spring Security模块;
  2. JWT的基本原理和用法;
  3. RESTfulAPI接口的设计和实现。

实现过程

1. 创建Spring Boot项目并导入依赖

在创建Spring Boot项目时,需要同时添加Spring Security和JWT的相关依赖。

<!-- Spring Security Core -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-core</artifactId>
    <version>5.1.6.RELEASE</version>
</dependency>

<!-- Spring Security Web -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>5.1.6.RELEASE</version>
</dependency>

<!-- Spring Security Config -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>5.1.6.RELEASE</version>
</dependency>

<!-- Spring MVC -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.3.9.RELEASE</version>
</dependency>

<!-- Jackson -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.8</version>
</dependency>

<!-- JWT -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

2. 配置Spring Security

在Spring Security的配置类中,需要定义用户身份认证和授权管理的相关信息。这里我们使用内存模式来存储用户信息。

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .authorizeRequests()
                .antMatchers("/api/v1/authenticate").permitAll()
                .anyRequest().authenticated()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService)
                .passwordEncoder(passwordEncoder());
    }

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

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.addAllowedOrigin("*");
        configuration.addAllowedMethod("*");
        configuration.addAllowedHeader("*");

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);

        return source;
    }
}

3. 实现用户登录

在用户登录过程中,需要检查用户的登录信息,并返回包含用户信息的JWT token。

@RestController
public class AuthController {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtUtils jwtUtils;

    @PostMapping("/api/v1/authenticate")
    public ResponseEntity<Object> authenticate(@RequestBody LoginDTO loginDTO) {
        try {
            authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(
                            loginDTO.getUsername(),
                            loginDTO.getPassword()
                    )
            );
        } catch (Exception e) {
            return ResponseEntity.badRequest().body("invalid username or password");
        }

        UserDetails userDetails = userDetailsService.loadUserByUsername(loginDTO.getUsername());
        String token = jwtUtils.generateToken(userDetails);

        return ResponseEntity.ok(new AuthToken(token));
    }
}

4. 实现用户注册和角色授权

在用户注册过程中,需要加密存储用户的密码信息,同时创建对应的用户角色信息(这里我们使用了简单的角色定义方式)。

@RestController
public class UserController {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @PostMapping("/api/v1/users")
    public ResponseEntity<Object> register(@RequestBody UserDTO userDTO) {
        User user = new User();
        user.setUsername(userDTO.getUsername());
        user.setPassword(passwordEncoder.encode(userDTO.getPassword()));
        user.setRole(userDTO.getRole());

        try {
            userDetailsService.loadUserByUsername(user.getUsername());
            return ResponseEntity.badRequest().body("user already exists");
        } catch (UsernameNotFoundException e) {}

        userDetailsService.createUser(user);

        return ResponseEntity.ok(user);
    }

    @PostMapping("/api/v1/users/{username}/roles")
    public ResponseEntity<Object> authorize(@PathVariable("username") String username, @RequestBody List<String> roles) {
        User user = (User) userDetailsService.loadUserByUsername(username);

        if (user == null) {
            return ResponseEntity.notFound().build();
        }

        user.setRoles(new HashSet<>(roles));
        userDetailsService.updateUser(user);

        return ResponseEntity.ok(user);
    }
}

5. 实现API接口的安全访问

在访问API接口时,需要使用用户的JWT token进行身份验证或授权管理,这里我们可以使用Spring Security提供的注解来实现。

@RestController
public class UserController {

    @GetMapping("/api/v1/users")
    public ResponseEntity<Object> getUsers() {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (principal instanceof UserDetails) {
            return ResponseEntity.ok("list of users");
        }

        return ResponseEntity.unauthorized().build();
    }

    @Secured("ROLE_ADMIN")
    @GetMapping("/api/v1/users/{username}")
    public ResponseEntity<Object> getUser(@PathVariable("username") String username) {
        return ResponseEntity.ok("user " + username);
    }
}

示例1:使用Postman测试

我们可以使用Postman来完成以下测试:

  1. 使用POST请求发送用户登录信息(例如:用户名为user,密码为password)获取JWT token;
  2. 使用JWT token作为请求头(Authorization:Bearer token)访问安全API接口。

示例2:使用Java代码验证

我们可以使用以下Java代码来测试:

  1. 创建一个基于Spring的Java应用程序;
  2. 使用Java程序访问安全API接口,通过JWT token验证和授权。
public class Client {

    public static void main(String[] args) {
        String token = "your_jwt_token_here";

        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", "Bearer " + token);
        HttpEntity<Object> requestEntity = new HttpEntity<>(headers);

        ResponseEntity<Object> responseEntity = restTemplate.exchange("http://localhost:8080/api/v1/users", HttpMethod.GET, requestEntity, Object.class);
        System.out.println(responseEntity.getBody());
    }
}

结论

通过本文的讲解,我们可以清晰地了解如何使用Spring Security和JWT来实现基于token的用户身份认证和授权管理,并提高安全性能和开发效率。在Spring MVC应用程序中,Spring Security已被广泛使用,因此我们可以用它来保护我们的业务数据和实现用户管理。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringSecurity详解整合JWT实现全过程 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • mybatis实现获取入参是List和Map的取值

    对于MyBatis,我们可以通过Mapper接口的方法的入参类型来传递参数。如果我们需要传递List或者Map类型的参数,该如何处理呢?下面我们来一一讲解。 传递List类型的参数 当我们需要将一个List类型的参数传递给Mapper接口的方法时,我们可以采用@Param注解的方式将参数进行命名,如下所示: public interface UserMapp…

    Java 2023年5月20日
    00
  • 浅析Java8新特性Lambda表达式和函数式接口

    浅析Java8新特性Lambda表达式和函数式接口 Java8引入了Lambda表达式和函数式接口,这是Java语言发展的一个重要里程碑。本文将深入浅出地介绍Lambda表达式和函数式接口的相关知识,包括什么是Lambda表达式,为什么要使用Lambda表达式,Lambda表达式的语法规则,Lambda表达式的应用场景,以及函数式接口相关的知识。 Lambd…

    Java 2023年5月26日
    00
  • gateway、webflux、reactor-netty请求日志输出方式

    为了让大家更好地了解 “gateway、webflux、reactor-netty请求日志输出方式”,我将分别讲解这三个主题,并提供相应的示例代码,在此之前,请确保已经安装好了Java环境,并了解基本的Spring Boot框架。 Gateway请求日志输出方式 Gateway是Spring Cloud的组件之一,可以将多个微服务组合起来作为一个整体对外提供…

    Java 2023年5月20日
    00
  • jsp实现局部刷新页面、异步加载页面的方法

    让我来为您详细讲解一下“JSP实现局部刷新页面、异步加载页面的方法”的完整攻略。 前言 JSP(Java Server Pages)是一种基于Java技术的Web开发技术,它允许开发人员在HTML标签中包含Java代码,并通过编译器将其转换为Java Servlet。JSP通常与MVC(Model-View-Controller)设计模式一起使用,它允许开发…

    Java 2023年6月15日
    00
  • MyBatis批量添加、修改和删除

    关于MyBatis批量添加、修改和删除的完整攻略,我会从以下几点进行详细讲解: 批量添加 INSERT INTO 批量修改 UPDATE 批量删除 DELETE 针对每个点,我会详细介绍其语法,以及两个示例。 1.批量添加 INSERT INTO 语法: <insert id="batchInsert" parameterType=…

    Java 2023年5月20日
    00
  • java Springboot实现多文件上传功能

    下面是Java SpringBoot实现多文件上传功能的完整攻略: 1. 搭建SpringBoot工程 首先我们需要通过Maven或Gradle来搭建一个SpringBoot工程,这里以Maven为例: <dependency> <groupId>org.springframework.boot</groupId> &lt…

    Java 2023年5月19日
    00
  • spring boot的maven配置依赖详解

    下面我将为你讲解“springboot的maven配置依赖详解”的完整攻略,包括以下内容: Maven介绍 Spring Boot Maven依赖配置详解 示例:添加Web依赖 示例:添加数据库依赖 1. Maven介绍 Maven是一个项目管理和构建自动化工具,它可以帮助Java项目进行构建、依赖管理和发布。Maven通过一组规范来描述项目的结构和依赖,并…

    Java 2023年5月15日
    00
  • Java使用SFTP上传文件到服务器的简单使用

    Java使用SFTP上传文件到服务器的简单使用 什么是SFTP SFTP(Secure File Transfer Protocol)是一种安全的文件传输协议,通过SFTP可以实现加密的文件传输。SFTP已经被广泛应用于网站部署、数据备份、文件同步等场景。 SFTP的工作原理 SFTP是基于SSH协议实现的,其工作原理与FTP比较类似,但是SFTP具有更高的…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部