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日

相关文章

  • SpringBoot一个非常蛋疼的无法启动的问题解决

    在使用Spring Boot开发应用程序时,有时会遇到无法启动的问题。以下是解决Spring Boot无法启动的一些常见问题和解决方法: 1. 端口被占用 问题描述 在启动Spring Boot应用程序时,可能会遇到以下错误: java.net.BindException: Address already in use: bind 解决方法 这个错误通常是由…

    Java 2023年5月14日
    00
  • Java中读取文件转换为字符串的方法

    想要读取文件并将其转换为字符串,可以使用Java中的流和缓冲区来实现。具体实现过程如下: 使用Java中的File类打开要读取的文件,可以使用文件的路径或URI来指定文件。例如,打开当前路径下的test.txt文件: File file = new File("test.txt"); 构造一个FileReader对象以读取文件内容。如果需…

    Java 2023年5月27日
    00
  • 举例讲解Java的JSON类库GSON的基本用法

    下面就给您详细讲解Java的JSON类库GSON的基本用法的攻略。 什么是GSON GSON是Google开发的用于Java解析JSON数据的类库。它可以将一个JSON字符串转化成Java对象,同样也可以将Java对象转化成对应的JSON字符串。GSON可以编码和解码任何Java对象。 导入GSON的Jar包 在使用GSON之前,我们需要先在项目中导入GSO…

    Java 2023年5月26日
    00
  • SpringBoot使用编程方式配置DataSource的方法

    当使用SpringBoot构建Web应用程序时,我们常常需要使用数据源,这里我们具体讲解使用编程方式配置DataSource的方法。 首先,需要在pom.xml文件中添加相应的依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactI…

    Java 2023年5月19日
    00
  • SpringBoot快速入门及起步依赖解析(实例详解)

    SpringBoot快速入门及起步依赖解析 SpringBoot是一个快速构建基于Spring的应用程序的框架。在本文中,我们将为您介绍如何快速入门以及如何使用起步依赖项。 快速入门 在使用SpringBoot之前,我们需要首先配置Maven或者Gradle来构建我们的应用程序。这里我们以Maven为例。 创建一个maven项目 使用Maven创建一个新项目…

    Java 2023年5月15日
    00
  • Spring Boot 配置大全(小结)

    针对“SpringBoot配置大全(小结)”这个主题,以下是一份完整攻略: SpringBoot配置大全(小结) 1. 配置文件 在Spring Boot中,我们可以通过application.properties或application.yml等配置文件来配置应用程序的相关属性。其中,application.yml文件采用了更加人性化的格式来展示配置信息。…

    Java 2023年5月15日
    00
  • java调用回调机制详解

    Java调用回调机制详解 回调机制是一种常见的编程技术,在Java编程中也得到了广泛应用。由于Java是面向对象的编程语言,因此回调机制在Java中也是以对象的方式实现的。 什么是回调机制? 简单来说,回调机制就是在完成某个操作后,由被调用者主动调用调用者的方法,执行一定的操作。在Java中,回调机制通常采用接口回调的形式实现。 在接口回调中,被调用者会提供…

    Java 2023年5月26日
    00
  • Spring获取ApplicationContext对象工具类的实现方法

    获取ApplicationContext对象是在使用Spring框架时非常常见的操作,可以方便地获取容器中的各种Bean实例。在Spring中,有多种方法可以获取ApplicationContext对象,下面给出了两种常用的方式: 方式一:通过注解@Autowried来获取ApplicationContext对象 import org.springframe…

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