Spring Security代码实现JWT接口权限授予与校验功能

为了实现JWT接口权限授予与校验功能,我们需要以下步骤:

1. 添加Spring Security和JWT依赖

Spring Security是一个现成的身份验证和授权框架,而JWT是一种安全性较高的身份认证方式。因此,我们需要添加相关依赖来支持这些功能。可以在Maven或Gradle中添加以下依赖:

<dependencies>
    ...
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.9.1</version>
    </dependency>
    ...
</dependencies>

2. 实现UserDetailsService

如果我们要使用Spring Security来实现身份验证和授权,那么我们需要实现一个UserDetailsService接口来加载用户信息。可以通过实现loadUserByUsername方法来返回一个UserDetails对象,Spring Security将使用该对象进行身份验证。

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String username) {
        // 从数据库或其他数据源加载用户信息
        User user = userRepository.findByUsername(username);

        if (user == null) {
            throw new UsernameNotFoundException("User not found with username: " + username);
        }

        return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(),
                new ArrayList<>());
    }
}

3. 实现JWT Token生成和校验

我们需要实现一个JWT Token工具类,用于生成和校验JWT Token。我们可以使用JJWT库来生成和解析JWT Token。

@Component
public class JwtTokenUtil {

    private static final String SECRET_KEY = "secret";

    public String generateToken(UserDetails userDetails) {
        // 设置Token过期时间为10小时
        long expirationTime = 36000000;

        return Jwts.builder()
                .setSubject(userDetails.getUsername())
                .setExpiration(new Date(System.currentTimeMillis() + expirationTime))
                .signWith(SignatureAlgorithm.HS512, SECRET_KEY)
                .compact();
    }

    public boolean validateToken(String token, UserDetails userDetails) {
        String username = extractUsername(token);

        return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
    }

    private Boolean isTokenExpired(String token) {
        final Date expiration = extractExpiration(token);
        return expiration.before(new Date());
    }

    private Date extractExpiration(String token) {
        return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody().getExpiration();
    }

    private String extractUsername(String token) {
        return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody().getSubject();
    }
}

4. 实现JWT过滤器

我们需要实现一个过滤器,用于在HTTP请求中解析JWT Token并在Spring Security中进行身份验证和授权。我们可以实现一个JwtRequestFilter类来处理此过程。

@Component
public class JwtRequestFilter extends OncePerRequestFilter {

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {

        final String authorizationHeader = request.getHeader("Authorization");

        String username = null;
        String jwt = null;

        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            jwt = authorizationHeader.substring(7);
            username = jwtTokenUtil.extractUsername(jwt);
        }

        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);

            if (jwtTokenUtil.validateToken(jwt, userDetails)) {
                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());

                usernamePasswordAuthenticationToken
                        .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
        }

        chain.doFilter(request, response);
    }
}

5. 配置Spring Security

我们需要配置Spring Security来允许对某些URL进行特殊的身份验证和授权。可以通过扩展WebSecurityConfigurerAdapter来实现此操作。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtRequestFilter jwtRequestFilter;

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }

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

        httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
    }
}

示例1

以下示例演示了如何在Spring Boot中使用JWT进行身份验证和授权。我们将获取JWT Token并在受保护的REST API上使用它来验证用户的身份。

@RestController
public class UserController {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @PostMapping("/authenticate")
    public ResponseEntity<?> createAuthenticationToken(@RequestBody AuthenticationRequest authenticationRequest)
            throws Exception {

        try {
            authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
                    authenticationRequest.getUsername(), authenticationRequest.getPassword()));
        } catch (BadCredentialsException e) {
            throw new Exception("Incorrect username or password", e);
        }

        final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());

        final String jwt = jwtTokenUtil.generateToken(userDetails);

        return ResponseEntity.ok(new AuthenticationResponse(jwt));
    }

    @GetMapping("/users")
    public List<User> getUsers() {
        return userService.findAll();
    }

    @PreAuthorize("hasRole('ADMIN')")
    @PostMapping("/users")
    public void addUser(@RequestBody User user) {
        userService.save(user);
    }
}

在上面的示例中,我们首先使用AuthenticationManager来进行身份验证。如果身份验证成功,将生成一个JWT Token并将其添加到响应中。

该代码还包括一个受保护的REST API,其中用户需要具有ADMIN角色才能访问。我们可以使用PreAuthorize注释来限制对此API的访问。在链式调用中使用了anyRequest().authenticated()来保护未受保护的REST端点,而permitAll()可用于允许所有用户获取JWT Token。

示例2

以下示例演示了如何在Spring Security中使用JWT进行授权和校验用户的身份。

@RestController
public class UserController {

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @GetMapping("/users")
    public List<User> getUsers(HttpServletRequest request) {
        String authorizationHeader = request.getHeader("Authorization");
        String jwtToken = authorizationHeader.substring(7);

        JwtClaims jwtClaims = Jwts.parser().setSigningKey(JwtTokenUtil.SECRET_KEY).parseClaimsJws(jwtToken).getBody();
        String username = jwtClaims.getSubject();

        UserDetails userDetails = userDetailsService.loadUserByUsername(username);

        if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
            return userService.findAll();
        } else {
            throw new UnauthorizedException("Invalid token");
        }
    }
}

在上面的示例中,我们从HTTP头中获取JWT Token,解析它并根据其内容加载用户信息。如果JWT Token是有效的,并且对当前请求的用户有授权,则我们可以执行请求。

我们还可以使用JwtTokenUtil来捕获JWToken并调用validateToken进行验证。如果验证成功,我们可以继续与请求。如果JWToken无效,则会抛出异常。

这里只是一个简单的示例,实际情况下可以根据需要进行更多的自定义授权和身份验证逻辑。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring Security代码实现JWT接口权限授予与校验功能 - Python技术站

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

相关文章

  • 常见的JVM参数有哪些?

    当我们运行Java程序时,JVM参数可以通过命令行传入,用于控制程序的行为和性能。下面介绍一些常用的JVM参数及其用法。 JVM参数列表 以下为常见的JVM参数列表: -Xmx: 设置Java堆内存的最大值 -Xms: 设置Java堆内存的初始值 -Xss: 设置线程栈的大小 -XX:PermSize: 设置永久代的初始值 -XX:MaxPermSize: …

    Java 2023年5月10日
    00
  • Java获取项目路径的多种方式

    获取Java Web项目路径是Java Web应用程序开发中的一个常见需求,以下是Java获取项目路径的多种方式: 使用getClassLoader获取项目路径 可以通过Thread.currentThread().getContextClassLoader().getResource(“”)来获取classpath下的路径 String path = Th…

    Java 2023年5月20日
    00
  • 详解Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)

    针对这个话题,我将分几个部分进行详细讲解。 1. 了解Java 网络IO编程 1.1 BIO BIO即Blocking IO,同步阻塞IO,应用方面比较广泛,缺点是每个客户端连接时都需要创建一个线程,因此比较消耗系统资源,如果客户端连接数比较少,建议使用BIO。 1.2 NIO NIO即Non-blocking IO,同步非阻塞IO,优点是可以支持多路复用,…

    Java 2023年5月23日
    00
  • 流式图表拒绝增删改查之框架搭建过程

    框架搭建过程可以分为以下几个步骤: 步骤一:确定需求和技术栈 首先需要明确项目的需求和技术栈。比如需要开发一个流式图表的应用,支持数据的实时更新和展示。技术栈可以选择 React,D3.js 等前端技术。如果需要后端支持,可以选择 Node.js,Python 等后端技术。 步骤二:搭建项目结构 接下来需要搭建项目的基本结构。可以使用 create-reac…

    Java 2023年5月20日
    00
  • Hibernate hql查询代码实例

    下面我来详细讲解“Hibernate hql查询代码实例”的完整攻略。 什么是Hibernate Hibernate是一个ORM框架(Object Relation Mapping),他能够将Java对象映射到关系数据库的数据表上,并提供了CRUD的操作方式。Hibernate可以用来解决JDBC API的繁琐操作。Hibernate的优点有: 减少了大量的…

    Java 2023年5月31日
    00
  • java控制台输出版多人聊天室

    Java控制台输出版多人聊天室是一种基于Java的多用户聊天程序,可以让多个用户在同一时间内进行聊天并且可以同时发送和接收消息。以下是一些步骤和示例,可以让您快速了解该聊天室的使用方法。 步骤: Step 1:编写代码 首先,需要编写Java代码来创建多人聊天室。这个过程可能相对复杂,涉及到网络编程以及多线程处理等知识点。因此,您可以参考其他开源项目或教程来…

    Java 2023年5月26日
    00
  • jquery ajaxfileupload异步上传插件

    jquery ajaxfileupload异步上传插件是一款可以在页面上实现文件异步上传的插件,可以帮助我们更方便地实现文件上传功能,并且使用方便、易于操作。下面是这款插件的完整攻略: 一、安装和引用 jquery ajaxfileupload异步上传插件可以使用npm包管理器进行安装,也可以使用CDN引入。以下是使用CDN引入的方法: <script…

    Java 2023年5月20日
    00
  • JDBC编程的详细步骤

    JDBC(Java Database Connectivity)是Java程序访问数据库的标准解决方案。下面,我将介绍JDBC编程的详细步骤,包括连接数据库、执行SQL语句等内容。 步骤一:导入JDBC驱动 通常情况下,你需要把特定数据库的JDBC驱动程序(JAR文件)导入到工程中,以便在程序中使用。不同数据库的JDBC驱动程序会有所不同,所以你需要确保使用…

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