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日

相关文章

  • Java日常练习题,每天进步一点点(60)

    首先,这是一篇Java日常练习题的攻略,包含了60个练习题目,帮助学习Java的人每天进步一点点。本文分为如下部分: 攻略简介 练习题目列表 示例说明 攻略简介 这篇攻略共包含了60个Java练习题目,力求帮助Java学习者过好编程的每一天。每个练习题目的描述都很清晰明了,题目中包含了需要完成的任务,做完题目后会有详细的答案和代码解释。通过这些练习题目的完成…

    Java 2023年5月23日
    00
  • SpringSecurity从数据库中获取用户信息进行验证的案例详解

    下面将为您详细讲解Spring Security从数据库中获取用户信息进行验证的攻略。 什么是Spring Security Spring Security是一个功能强大、可高度定制的认证和授权框架,可用于保护基于Spring的Java应用程序。它提供了基于角色、用户和访问级别的身份验证和授权,以及多种身份验证选项,包括基本身份验证、OAuth和JWT等。 …

    Java 2023年5月20日
    00
  • MyBatis动态SQL实现配置过程解析

    下面是”MyBatis动态SQL实现配置过程解析”的完整攻略: 1. 什么是动态SQL 在实际开发中,SQL语句通常不是固定的,而是需要根据具体情况动态生成。MyBatis通过动态SQL实现可以生成不同的SQL语句,以满足各种业务需求。 2. 实现动态SQL MyBatis提供了以下标签来实现动态SQL: 2.1 \标签 用于判断一个条件是否成立,如果成立,…

    Java 2023年5月20日
    00
  • Java简单工厂模式详细解释

    Java简单工厂模式详细解释 简介 简单工厂模式是创建型模式的一种,它提供了一种创建对象的最佳方法。在简单工厂模式中,我们在创建对象的时候不会对客户端暴露创建逻辑,而是通过一个公共的静态方法返回一个新的对象。简单工厂模式属于类的创建型模式,在工厂类中,选择创建哪一种产品类的实例化是由工厂来决定的,而并非由客户端来决定。 实现 简单工厂模式的实现需要下面几个角…

    Java 2023年5月19日
    00
  • 什么是Java代码优化?

    Java代码优化指的是通过改进代码的设计、实现和运行等方面,使得Java程序的性能更高、消耗的资源更少,同时保证程序的正确性和可维护性。下面给出一个Java代码优化的使用攻略。 步骤一:明确优化目标 优化目标应该具体、明确、可衡量以及符合业务需求。可能的优化目标包括: 提高程序的运行速度,减少响应时间。 降低程序的系统资源消耗,例如CPU占用率、内存占用等。…

    Java 2023年5月11日
    00
  • 详解Html a标签中href和onclick用法、区别、优先级别

    下面是详解Html a标签中href和onclick用法、区别、优先级别的攻略。 href和onclick用法简介 在HTML中,a标签用于创建超链接,它允许在文档之间或页面内的不同部分之间创建链接。a标签有两个最重要的属性:href和onclick。 href属性:规定链接的目标URL地址,点击链接会跳转到指定的URL地址。 onclick属性:定义元素被…

    Java 2023年6月15日
    00
  • JSP中 Session和作用域的使用

    下面是关于“JSP中 Session和作用域的使用”的完整攻略。 什么是Session和作用域 在JSP中,”作用域(Scope)”是指在某个特定的范围内,程序可以访问到的变量。JSP中的作用域是从大到小,依次为:application、session、request和page。 其中,”Session”就是 Session 作用域,代表一个用户会话过程,当…

    Java 2023年6月15日
    00
  • extjs 学习笔记 四 带分页的grid

    下面是针对“EXTJS 学习笔记 四 —— 带分页的 Grid”这篇文章的详细攻略。 1. 文章概览 该篇文章主要是介绍如何使用 EXTJS 构建具有分页功能的 Grid 表格。其中,主要介绍以下内容: 引入必要的资源文件 创建分页工具栏 构建 Grid 表格 设置 Grid 表格分页参数 2. 引入必要的资源文件 在使用 EXTJS 构建 Grid 表格时…

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