SpringBoot+SpringSecurity+JWT实现系统认证与授权示例

下面是“SpringBoot+SpringSecurity+JWT实现系统认证与授权”的完整攻略:

一、什么是Spring Boot、Spring Security和JWT

  • Spring Boot:是一个快速开发框架,能够简化Spring应用程序的创建和开发过程。
  • Spring Security:是Spring框架中提供的一套安全服务框架,可以用来保护Web应用程序,场景包括认证(authentication)、授权(authorization)和密码学(cryptography)等。
  • JWT(JSON Web Token):是一种基于JSON的轻量级授权和身份验证协议,主要用于Web应用程序和API的安全传输。

二、如何使用Spring Boot、Spring Security和JWT

  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.0</version>
</dependency>
  1. 配置Spring Security和JWT相关属性
    在application.yml文件中添加以下配置:
#JWT配置
jwt:
  header:
    name: Authorization
    prefix: Bearer
    secret: JWTSecretKey
    expiration: 604800000 #7天过期时间,单位毫秒
# 关闭csrf验证,jwt不需要csrf
security:
  csrf:
    enabled: false
  1. 实现Spring Security的认证和授权逻辑
    自定义一个继承了WebSecurityConfigurerAdapter类的WebSecurityConfig类,重写configure方法来实现相应的认证和授权逻辑。
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    //在这里重写configure方法来实现相应的认证和授权逻辑
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.csrf().disable()
                .authorizeRequests()
                .antMatchers("/api/authenticate").permitAll()
                .anyRequest().authenticated()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

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

    @Bean
    public JwtAuthFilter authenticationJwtTokenFilter() {
        return new JwtAuthFilter();
    }
}
  1. 实现JWT的Token生成和解析逻辑
    自定义一个JwtUtils类,实现JWT的Token生成和解析逻辑。
@Component
public class JwtUtils {
    private String jwtSecret = "JWTSecretKey";
    private int jwtExpirationMs = 604800000; //7天过期时间,单位毫秒

    public String generateJwtToken(Authentication authentication) {
        UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal();
        return Jwts.builder()
                .setSubject((userPrincipal.getUsername()))
                .setIssuedAt(new Date())
                .setExpiration(new Date((new Date()).getTime() + jwtExpirationMs))
                .signWith(SignatureAlgorithm.HS512, jwtSecret)
                .compact();
    }

    public String getUsernameFromJwtToken(String token) {
        return Jwts.parser()
                .setSigningKey(jwtSecret)
                .parseClaimsJws(token)
                .getBody().getSubject();
    }
}
  1. 实现JWT的认证过滤器逻辑
    自定义一个JwtAuthFilter类,实现JWT的认证过滤器逻辑。
public class JwtAuthFilter extends OncePerRequestFilter {
    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain)
            throws ServletException, IOException {
        try {
            String jwt = parseJwt(request);
            if (jwt != null && jwtUtils.validateJwtToken(jwt)) {
                String username = jwtUtils.getUsernameFromJwtToken(jwt);

                UserDetails userDetails = userDetailsService.loadUserByUsername(username);
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        } catch (Exception e) {
            logger.error("Cannot set user authentication: {}", e);
        }

        filterChain.doFilter(request, response);
    }

    private String parseJwt(HttpServletRequest request) {
        String headerAuth = request.getHeader("Authorization");

        if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) {
            return headerAuth.substring(7, headerAuth.length());
        }

        return null;
    }
}
  1. 实现UserDetails的逻辑
    自定义一个实现UserDetails接口的UserDetailsImpl类。
public class UserDetailsImpl implements UserDetails {
    private Integer id;
    private String username;
    private String password;
    private Collection<? extends GrantedAuthority> authorities;

    public UserDetailsImpl(Integer id, String username, String password,
                            Collection<? extends GrantedAuthority> authorities) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.authorities = authorities;
    }

    public static UserDetailsImpl build(User user) {
        List<GrantedAuthority> authorities = user.getRoles().stream()
                .map(role -> new SimpleGrantedAuthority(role.getName().name()))
                .collect(Collectors.toList());

        return new UserDetailsImpl(
                user.getId(),
                user.getUsername(),
                user.getPassword(),
                authorities);
    }
    //省略getter和setter方法以及其他接口方法的实现
}
  1. 实现UserDetailsService的逻辑
    自定义一个实现UserDetailsService接口的UserDetailsServiceImpl类。
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    @Autowired
    UserRepository userRepository;

    @Override
    @Transactional
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("User Not Found with username: " + username));

        return UserDetailsImpl.build(user);
    }
}

至此,我们完成了使用Spring Boot、Spring Security和JWT来实现系统认证与授权的全部步骤。

三、示例

下面是两个示例,演示如何使用Spring Boot、Spring Security和JWT来实现系统认证与授权。

示例一:用户认证

实现基于SpringBoot、SpringSecurity和JWT的用户认证演示程序,可参考以下代码:

@RestController
@RequestMapping("/api")
public class AuthController {
    @Autowired
    AuthenticationManager authenticationManager;

    @Autowired
    JwtUtils jwtUtils;

    @PostMapping("/authenticate")
    public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));

        SecurityContextHolder.getContext().setAuthentication(authentication);

        String jwt = jwtUtils.generateJwtToken(authentication);

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

示例二:资源授权

实现基于SpringBoot、SpringSecurity和JWT的资源授权演示程序,可参考以下代码:

@RestController
@RequestMapping("/api")
public class UserController {
    @Autowired
    UserRepository userRepository;

    @GetMapping("/users/{id}")
    @PreAuthorize("hasRole('USER') or hasRole('ADMIN')")
    public ResponseEntity<User> getUserById(@PathVariable(value = "id") Integer userId) {
        User user = userRepository.findById(userId).orElseThrow(() -> new ResourceNotFoundException("User", "id", userId));
        return ResponseEntity.ok().body(user);
    }
}

在这个示例中,我们使用了@PreAuthorize注解,它表示只有在用户有“USER”或“ADMIN”角色时才能访问该接口。

以上是关于“SpringBoot+SpringSecurity+JWT实现系统认证与授权示例”的完整攻略。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot+SpringSecurity+JWT实现系统认证与授权示例 - Python技术站

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

相关文章

  • servlet监听实现统计在线人数功能 附源码下载

    这里提供一个基于Servlet监听器的统计在线人数的实现方法,如果学习Java Web开发,这是一道需要掌握的入门练习题目。 实现思路 编写一个Servlet监听器,实现 ServletContextAttributeListener 接口 在监听器中编写监听器方法,实现当用户绘制request时添加ServletContextListener储存在线人数,…

    Java 2023年6月15日
    00
  • Java 添加Word目录的2种方法示例代码详解

    针对你提出的问题,我来进行详细讲解。 标题 首先,我们要为这篇攻略添加一个合适的标题,比如“Java 添加Word目录的2种方法示例代码详解”。 介绍 在正式讲解之前,我们需要先给读者介绍一下本篇攻略的背景和目的。这里我们可以写一段简短的介绍: 本篇攻略将为大家介绍如何在Java中添加Word目录的两种方法,并提供相应的示例代码进行演示。其中,第一种方法使用…

    Java 2023年5月19日
    00
  • Sprint Boot @ResponseBody使用方法详解

    Spring Boot的@ResponseBody的作用与使用方法 在Spring Boot中,@ResponseBody注解用于将方法的返回值转换为指定格式的响应体。通过使用@ResponseBody注解,可以将方法的返回值转换为JSON、XML等格式的响应体,以便客户端进行处理。 @ResponseBody注解的作用 @ResponseBody注解用于将…

    Java 2023年5月5日
    00
  • php URL跳转代码 减少外链

    PHP URL跳转代码用于将一个URL重定向到另一个URL,可以帮助网站管理者减少外链,从而提高网站的安全性,避免了在跨域请求过程中被注入恶意代码的风险。下面将为你详细讲解如何使用PHP URL跳转代码来减少外链。 准备工作 在进行URL跳转之前,你需要知道一些准备工作。首先,需要安装一台web服务器,比如说Apache。其次,需要安装PHP,以便在PHP代…

    Java 2023年6月16日
    00
  • Hibernate识别数据库特有字段实例详解

    让我为您详细讲解“Hibernate识别数据库特有字段实例详解”的完整攻略。 在使用Hibernate进行开发时,有些时候我们需要识别一些数据库特有的字段,如MySQL中的ENUM类型、PostgreSQL中的ARRAY类型等。这些字段并不在Hibernate的基础数据类型中,所以我们需要进行额外配置。 下面是如何识别MySQL中的ENUM类型的示例: 首先…

    Java 2023年5月20日
    00
  • 微信开发准备第二步 springmvc mybatis项目结构搭建

    微信开发准备第二步 springmvc mybatis项目结构搭建是微信公众号开发的重要步骤之一。下面是该步骤的完整攻略: 步骤一:创建Maven项目 我们可以使用Maven来创建一个新的SpringMVC MyBatis项目。在创建项目时,我们需要选择“webapp”类型的项目,并添加SpringMVC和MyBatis的依赖。下面是一个示例的pom.xml…

    Java 2023年5月17日
    00
  • JPype实现在python中调用JAVA的实例

    JPype是一个开源的Python模块,它可以让Python程序调用Java类。使用JPype可以方便地使用Java已有的库,从而加速Python在特定场景下的运行效率。下面是在Python中使用JPype调用Java实例的详细攻略: 1. 安装JPype 安装JPype模块前,需要Python和Java环境同时存在于计算机中。如果没有安装Java环境,可以…

    Java 2023年6月15日
    00
  • SpringSecurity解决POST方式下CSRF问题

    SpringSecurity是Spring Framework的一个安全框架,它提供了完善的认证授权机制和攻击防护机制。其中,CSRF跨站请求伪造攻击是常见的一种攻击方式,SpringSecurity提供了一系列的解决方案来应对该问题。 以下是使用SpringSecurity解决POST方式下CSRF问题的完整攻略: 第一步:添加SpringSecurity…

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