Springboot+SpringSecurity+JWT实现用户登录和权限认证示例

让我为您详细讲解一下“Springboot+SpringSecurity+JWT实现用户登录和权限认证示例”的攻略。

首先,需要安装以下工具:

  • Java开发环境
  • Maven构建工具

然后,我们需要按照以下步骤进行实现:

1.添加依赖

在pom.xml文件中添加以下依赖:

<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>

2.配置JWT

在配置类中添加JWT的秘钥,过期时间等信息:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private static final String SECRET_KEY = "secretKey";
    private static final long EXPIRATION_TIME = 864_000_000; // 10 days

    @Bean
    public JwtBuilder jwtBuilder() {
        return Jwts.builder().setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                .signWith(Keys.hmacShaKeyFor(SECRET_KEY.getBytes()));
    }
}

3.实现用户校验

自定义UserDetailsService,实现用户校验,并将其注入到Spring Security中:

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    private final UserRepository userRepository;

    public UserDetailsServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Optional<User> userOptional = userRepository.findByUsername(username);
        if (userOptional.isEmpty()) {
            throw new UsernameNotFoundException("User not found");
        }

        User user = userOptional.get();
        return new UserPrincipal(user.getUsername(), user.getPassword(), Collections.emptyList());
    }
}

其中,User是自定义的用户实体类,UserRepository是自定义的用户DAO层。

4.实现AuthenticationProvider

自定义一个AuthenticationProvider,实现用户自定义校验:

@Component
public class JwtAuthenticationProvider implements AuthenticationProvider {

    private static final String AUTHORIZATION_HEADER = "Authorization";
    private static final String TOKEN_PREFIX = "Bearer ";

    private final JwtParser jwtParser;

    public JwtAuthenticationProvider(JwtParser jwtParser) {
        this.jwtParser = jwtParser;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String authorizationHeader = request.getHeader(AUTHORIZATION_HEADER);

        if (StringUtils.isEmpty(authorizationHeader) || !authorizationHeader.startsWith(TOKEN_PREFIX)) {
            throw new BadCredentialsException("Authorization token not found");
        }

        String token = authorizationHeader.replace(TOKEN_PREFIX, "");
        Claims claims = jwtParser.parseClaimsJws(token).getBody();

        String username = claims.getSubject();

        if (username == null) {
            throw new BadCredentialsException("Invalid token");
        }

        return new UsernamePasswordAuthenticationToken(username, "", Collections.emptyList());
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return JwtAuthenticationToken.class.isAssignableFrom(aClass);
    }
}

其中,JwtAuthenticationToken是自定义的Token类,JwtParser是JWT解析器。

5.配置Spring Security

在WebSecurityConfigurerAdapter子类中重写configure方法,配置拦截规则和认证方式:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final UserDetailsService userDetailsService;
    private final JwtBuilder jwtBuilder;
    private final JwtParser jwtParser;

    public SecurityConfig(UserDetailsService userDetailsService, JwtBuilder jwtBuilder, JwtParser jwtParser) {
        this.userDetailsService = userDetailsService;
        this.jwtBuilder = jwtBuilder;
        this.jwtParser = jwtParser;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable()
            .authorizeRequests()
            .antMatchers(HttpMethod.POST, "/login").permitAll()
            .anyRequest().authenticated()
            .and()
            .addFilter(new JwtAuthenticationFilter(authenticationManager(), jwtBuilder))
            .addFilter(new JwtAuthorizationFilter(authenticationManager(), jwtParser))
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

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

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

其中,JwtAuthenticationFilter是自定义的Token过滤器,JwtAuthorizationFilter是自定义的权限过滤器。

至此,我们已经成功地实现了Springboot+SpringSecurity+JWT的用户登录和权限认证。

下面,我们来看一下示例代码:

示例1:用户登录

@PostMapping("/login")
public LoginResponse login(@RequestBody LoginRequest request) {
    Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword()));

    String token = jwtBuilder.signWith(SignatureAlgorithm.HS512, SECRET_KEY)
            .setSubject(request.getUsername())
            .compact();

    return new LoginResponse(token);
}

其中,LoginRequest是请求实体类,LoginResponse是响应实体类。

示例2:根据权限获取用户信息

@GetMapping("/me")
@PreAuthorize("hasAnyRole('ADMIN')")
public UserResponse me() {
    UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    User user = userRepository.findByUsername(userDetails.getUsername()).orElseThrow(() -> new RuntimeException("User not found"));

    return new UserResponse(user.getUsername(), user.getEmail());
}

其中,PreAuthorize是Spring Security的注解,表示请求需要具有特定的角色或权限。

希望这段内容能够对您有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Springboot+SpringSecurity+JWT实现用户登录和权限认证示例 - Python技术站

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

相关文章

  • Spring Security密码解析器PasswordEncoder自定义登录逻辑

    下面是详细讲解“Spring Security密码解析器PasswordEncoder自定义登录逻辑”的完整攻略: 1. 理解PasswordEncoder和其实现类 PasswordEncoder是Spring Security中的一个接口,用于加密和解密用户登录密码,在用户登录过程中用于比对用户输入的密码和数据库中存储的加密后的密码是否一致。 Sprin…

    Java 2023年5月20日
    00
  • Java计算一个数加上100是完全平方数,加上168还是完全平方数

    题目简述:Java计算一个数加上100是完全平方数,加上168还是完全平方数 根据题目中的描述,可以得到以下两个方程:1. n + 100 = x^22. n + 168 = y^2 其中,n表示待求解的数,x和y分别是n加上100和n加上168后所对应的完全平方数。 这两个方程可以同时求解,步骤如下: 首先,对于x^2和y^2,我们可以利用Java的Mat…

    Java 2023年5月19日
    00
  • Java如何实现简单的RPC框架

    RPC(Remote Procedure Call)是一种面向服务的RPC(Remote Procedure Call)请求响应协议。 Java提供了众多实现RPC框架的库,其中比较著名的有Dubbo、Thrift、 gRPC等。下面我们以Dubbo框架为例,详细讲解Java如何实现简单的RPC框架。 1. Dubbo框架简介 Dubbo是一个RPC框架,支…

    Java 2023年5月18日
    00
  • Java 正则表达式入门详解(基础进阶)

    Java 正则表达式入门详解(基础进阶) 什么是正则表达式? 正则表达式是一种用来匹配字符串的模式,通常用来检索、替换那些符合某个规则的文本。在Java中,正则表达式是通过java.util.regex包来实现的。 正则表达式的基本语法 在Java中,正则表达式的基本语法有以下几种: 字符: 表示匹配某个字符,例如匹配单个字符a,使用正则表达式a即可。 字符…

    Java 2023年5月23日
    00
  • 超细讲解Java调用python文件的几种方式

    恭喜您,这是一个非常有用的话题。在本篇文章中,我们将会深入探讨Java调用Python文件操作的几种方式。下面是完整攻略的具体内容。 1.首选Java调用Python文件的方式:Jython Jython(Java Python)是一种Python解释器,它使用Java语言编写,可以让Python代码在Java环境下运行。Jython具有明显的优势,可以很好…

    Java 2023年5月19日
    00
  • Springboot安全框架整合SpringSecurity实现方式

    Spring Boot 安全框架整合 Spring Security 实现方式 Spring Boot 是基于 Spring 框架的快速开发框架,而 Spring Security 是 Spring 生态中的安全框架,提供了安全认证、授权等功能。本文将介绍如何在 Spring Boot 中整合 Spring Security 实现安全认证和授权。 Sprin…

    Java 2023年5月20日
    00
  • java生成随机数(字符串)示例分享

    下面是详细的完整攻略: 标题:Java生成随机数(字符串)示例分享 1. 生成随机整数 Java生成随机整数可以通过使用Java中的random类实现。以下是一个示例代码,生成一个1-100之间的随机整数: import java.util.Random; public class GenerateRandomNumber { public static v…

    Java 2023年5月27日
    00
  • 常见的Java调试器有哪些?

    Java调试器是一种用于调试Java应用程序和Java虚拟机(JVM)的工具,它可以帮助开发人员在开发Java应用程序时快速定位和解决程序中的错误。常见的Java调试器有以下几种: Eclipse调试器 IntelliJ IDEA调试器 NetBeans调试器 JDB调试器 以下是常见的Java调试器的详细使用攻略: 1. Eclipse调试器使用攻略 Ec…

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