前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用Spring Security和JWT来进行身份验证和授权(三)

使用Spring Security和JWT来进行身份验证和授权(三)

原创
作者头像
堕落飞鸟
发布2023-04-14 07:25:18
1.8K0
发布2023-04-14 07:25:18
举报
文章被收录于专栏:飞鸟的专栏

实现身份验证和授权

接下来,我们需要实现基于JWT的身份验证和授权。可以使用以下代码实现:

代码语言:javascript
复制
@Service
public class JwtUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        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<>());
    }

}

上述代码中,我们定义了一个名为“JwtUserDetailsService”的类,它实现了UserDetailsService接口。该类从数据库中获取用户信息,并将其转换为Spring Security用户详细信息对象。

接下来,我们需要实现JWT身份验证入口点。可以使用以下代码实现:

代码语言:javascript
复制
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException authException) throws IOException, ServletException {
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
    }

}

上述代码中,我们定义了一个名为“JwtAuthenticationEntryPoint”的类,它实现了AuthenticationEntryPoint接口。该类用于在未经身份验证的情况下拒绝请求,并返回HTTP状态代码401。

最后,我们需要实现JWT请求过滤器。可以使用以下代码实现:

代码语言:javascript
复制
@Component
public class JwtRequestFilter extends OncePerRequestFilter {

    @Autowired
    private JwtUserDetailsService jwtUserDetailsService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        final String requestTokenHeader = request.getHeader("Authorization");

        String username = null;
        String jwtToken = null;
        if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
            jwtToken = requestTokenHeader.substring(7);
            try {
                username = jwtTokenUtil.getUsernameFromToken(jwtToken);
            } catch (IllegalArgumentException e) {
                logger.error("Unable to get JWT Token");
            } catch (ExpiredJwtException e) {
                logger.error("JWT Token has expired");
            }
        } else {
            logger.warn("JWT Token does not begin with Bearer String");
        }

        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {

            UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(username);

            if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {

                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                usernamePasswordAuthenticationToken
                        .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
        }
        chain.doFilter(request, response);
    }

}

上述代码中,我们定义了一个名为“JwtRequestFilter”的类,它扩展了Spring Security的OncePerRequestFilter类。该类用于过滤所有请求,并验证JWT令牌。如果JWT令牌有效,则设置Spring Security上下文的身份验证信息。

现在我们需要将这些组件集成到我们的Spring Boot应用程序中。可以使用以下代码实现:

代码语言:javascript
复制
@Configuration
@EnableWebSecurity
public class SecurityConfigurer extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

    @Autowired
    private JwtUserDetailsService jwtUserDetailsService;

    @Autowired
    private JwtRequestFilter jwtRequestFilter;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
    }

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

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.csrf().disable().authorizeRequests().antMatchers("/authenticate").permitAll().anyRequest()
                .authenticated().and().exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
                .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
    }
}

上述代码中,我们定义了一个名为“SecurityConfigurer”的类,它扩展了Spring Security的WebSecurityConfigurerAdapter类。该类用于配置身份验证和授权规则,以及安全过滤器链。我们在这里配置了以下内容:

  • 我们允许访问“/authenticate”端点而不需要身份验证。这是我们用于生成JWT令牌的端点。
  • 我们要求对所有其他请求进行身份验证。
  • 我们配置了JWT身份验证入口点(jwtAuthenticationEntryPoint)和JWT请求过滤器(jwtRequestFilter)。
  • 我们配置了会话管理策略为“STATELESS”,这意味着我们将不使用HTTP会话进行身份验证和授权。
  • 我们将JWT请求过滤器添加到Spring Security的过滤器链中。它应该在用户名密码身份验证过滤器之前运行。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 实现身份验证和授权
相关产品与服务
多因子身份认证
多因子身份认证(Multi-factor Authentication Service,MFAS)的目的是建立一个多层次的防御体系,通过结合两种或三种认证因子(基于记忆的/基于持有物的/基于生物特征的认证因子)验证访问者的身份,使系统或资源更加安全。攻击者即使破解单一因子(如口令、人脸),应用的安全依然可以得到保障。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档