介绍
在开发 web 应用程序时,安全权限控制是非常重要的一项功能。使用 Spring Boot、Spring Security 和 JWT(JSON Web Token)可以帮助我们实现简单且强大的 RESTful API 权限控制。
环境准备
首先,确保你的开发环境配置好了以下组件:
- JDK 1.8 或以上版本
- Maven 3.x 或以上版本
创建 Spring Boot 项目
使用 Maven 创建一个新的 Spring Boot 项目,执行以下命令:
mvn archetype:generate -DgroupId=com.example -DartifactId=spring-boot-security-jwt-demo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
添加依赖
在项目的 pom.xml 文件中添加以下依赖:
<dependencies>
    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Spring Security -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <!-- JWT -->
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.11.2</version>
    </dependency>
</dependencies>
配置 Spring Security
在 Spring Boot 项目的 application.properties 文件中添加以下配置:
# 禁用 security 默认的 http basic 认证方式
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
然后,创建一个 SecurityConfig 类,配置 Spring Security:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserService userService;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .authorizeRequests()
                .antMatchers(HttpMethod.POST, "/api/authenticate").permitAll()
                .anyRequest().authenticated()
                .and()
            .addFilter(new JwtAuthenticationFilter(authenticationManager()))
            .addFilter(new JwtAuthorizationFilter(authenticationManager()))
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
上面的配置禁用了 Spring Security 的默认 http basic 认证方式,并指定了登录接口 /api/authenticate 不需要认证即可访问。
定义用户服务
创建一个 UserService 接口,并实现 UserDetailsService:
@Service
public class UserService implements UserDetailsService {
    @Autowired
    private UserRepository userRepository;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException(username);
        }
        return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), new ArrayList<>());
    }
}
定义数据模型
创建一个 User 实体类来表示用户对象,并创建一个 UserRepository 接口继承自 JpaRepository:
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String password;
    // getters and setters
}
public interface UserRepository extends JpaRepository<User, Long> {
    User findByUsername(String username);
}
实现认证和授权过滤器
创建一个 JwtAuthenticationFilter 类来处理认证逻辑:
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    private AuthenticationManager authenticationManager;
    public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
        setFilterProcessesUrl("/api/authenticate");
    }
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        try {
            User user = new ObjectMapper().readValue(request.getInputStream(), User.class);
            return authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), new ArrayList<>())
            );
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        String token = Jwts.builder()
                .setSubject(((User) authResult.getPrincipal()).getUsername())
                .claim("authorities", new ArrayList<>())
                .setExpiration(new Date(System.currentTimeMillis() + 864000000))
                .signWith(SignatureAlgorithm.HS512, "SecretKeyToGenJWTs".getBytes())
                .compact();
        response.addHeader("Authorization", "Bearer " + token);
    }
}
创建一个 JwtAuthorizationFilter 类来处理授权逻辑:
public class JwtAuthorizationFilter extends BasicAuthenticationFilter {
    public JwtAuthorizationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        String header = request.getHeader("Authorization");
        if (header == null || !header.startsWith("Bearer ")) {
            chain.doFilter(request, response);
            return;
        }
        UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        chain.doFilter(request, response);
    }
    private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        if (token != null) {
            String user = Jwts.parser()
                    .setSigningKey("SecretKeyToGenJWTs".getBytes())
                    .parseClaimsJws(token.replace("Bearer ", ""))
                    .getBody()
                    .getSubject();
            if (user != null) {
                return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
            }
            return null;
        }
        return null;
    }
}
创建 RESTful API
创建一个 UserController 类来处理用户相关的 API:
@RestController
@RequestMapping("/api/users")
public class UserController {
    @GetMapping
    public List<User> getAllUsers() {
        // 获取所有用户的逻辑
    }
    @GetMapping("/{id}")
    public User getUserById(@PathVariable Long id) {
        // 根据用户 ID 获取用户的逻辑
    }
    @PostMapping
    public User createUser(@RequestBody User user) {
        // 创建用户的逻辑
    }
    @PutMapping("/{id}")
    public User updateUser(@PathVariable Long id, @RequestBody User user) {
        // 更新用户的逻辑
    }
    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable Long id) {
        // 删除用户的逻辑
    }
}
运行项目
运行项目并访问相应的 API 接口,例如:
curl -X GET http://localhost:8080/api/users
你可以使用 Postman 或其他工具来测试各个接口。
结束语
通过使用 Spring Boot、Spring Security 和 JWT,我们实现了简单且强大的 RESTful API 权限控制。这样的安全机制可以保护我们的应用程序,确保只有经过授权的用户才能访问敏感资源。
希望这篇博客对你了解 Spring Boot + Spring Security + JWT 的实际应用有所帮助,加油!
本文来自极简博客,作者:梦境旅人,转载请注明原文链接:Spring Boot Spring Security JWT 实现简单的 RESTful API 权限控制
 
        
         
                 微信扫一扫,打赏作者吧~
微信扫一扫,打赏作者吧~