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日

相关文章

  • 详解使用Spring的BeanPostProcessor优雅的实现工厂模式

    下面我将详细讲解使用Spring的BeanPostProcessor实现工厂模式的方法。 什么是工厂模式 首先,工厂模式是一种创建型设计模式,主要思想是将对象的创建过程封装在一个工厂类中,从而使得代码更加具有可扩展性和可维护性。在实现过程中,我们可以使用多种方式来封装对象的创建过程,比如工厂方法模式和抽象工厂模式。 什么是BeanPostProcessor …

    Java 2023年5月19日
    00
  • Spring框架生成图片验证码实例

    让我来详细讲解一下“Spring框架生成图片验证码实例”的完整攻略。 1. 环境搭建 首先,我们需要搭建好Spring MVC环境,这里就不做过多的讲解了。如果你还不熟悉Spring MVC的环境搭建,可以先学习一下相关的教程,在此不再赘述。 2. 添加依赖 在我们项目的pom.xml文件中,我们需要添加以下依赖: <!– SpringSecurit…

    Java 2023年6月15日
    00
  • dl、dt、dd 标记来改造163邮箱的广告条

    如果想要改造网页上的广告条,可以使用HTML中的dl、dt、dd标记来达到目的。下面是详细的攻略: 1.使用dl、dt、dd标记 dl标记用于定义一个描述列表(description list),dt标记用于定义列表项中的项目名称(即定义术语或名称),dd标记用于定义项目的描述。可以使用这些标记分别定义广告条的标题、说明和一个链接。 2.示例一 下面是一个针…

    Java 2023年6月15日
    00
  • Java 数组内置函数toArray详解

    Java 数组内置函数 toArray 详解 toArray() 是 Java 数组的内置函数之一。它可以将一个数组转换成一个目标类型的数组。在这篇文章中,我们将探讨 toArray() 函数的使用以及一些示例。 toArray() 函数的使用 toArray() 函数的基本形式如下: public <T> T[] toArray(T[] a) …

    Java 2023年5月26日
    00
  • java文件操作工具类实现复制文件和文件合并

    针对这个问题,我会从以下几个方面进行讲解: Java文件操作的基础知识 复制文件的实现方法 合并文件的实现方法 工具类的封装实现 两条示例 1. Java文件操作的基础知识 在Java中,文件的读写操作通常使用IO流来进行。Java提供了两种类型的IO流:字节流和字符流。其中字节流可以处理所有类型的文件,而字符流只能处理文本文件。因此,在文件复制和合并操作中…

    Java 2023年5月20日
    00
  • Spring+SpringMVC+MyBatis整合详细教程(SSM)

    以下是关于“Spring+SpringMVC+MyBatis整合详细教程(SSM)”的完整攻略,其中包含两个示例。 1. 前言 Spring+SpringMVC+MyBatis整合(简称SSM)是一种常用的Java Web开发框架,它将Spring、SpringMVC和MyBatis三个框架整合在一起,提供了一种灵活的方式来开发Web应用程序。本攻略将详细讲…

    Java 2023年5月16日
    00
  • Spring Boot Maven 打包可执行Jar文件的实现方法

    实现Spring Boot Maven打包成可执行Jar文件的实现方法,主要有两种。 1. 使用Spring Boot Maven插件打包 首先,需要在pom.xml文件中,引入Spring Boot Maven插件,具体如下: <build> … <plugins> … <plugin> <groupId&…

    Java 2023年5月20日
    00
  • 使用SpringBoot 工厂模式自动注入到Map

    使用SpringBoot工厂模式自动注入到Map的完整攻略 在Spring Boot中,我们可以使用工厂模式将一组相关的类进行组合,并将它们自动注入到Map中。这种方式可以帮助我们更加灵活地管理和使用这些类。本文将详细讲解使用Spring Boot工厂模式自动注入到Map的完整攻略,包括以下内容: 工厂模式的基本概念 Spring Boot中的工厂模式实现方…

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