当前位置: 首页 > 知识库问答 >
问题:

如何从JWT身份验证筛选器中抛出自定义异常

尹冠宇
2023-03-14

我在Project中使用了Spring Boot和JWT以及Spring security。Spring Boot:2.3.5.发布JJWT Verison:0.11.2

import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;

import io.jsonwebtoken.Claims;

public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        String header = request.getHeader(JwtConstant.AUTHORIZATION);

        if (StringUtils.isNotBlank(header) && header.startsWith(JwtConstant.BEARER)) {

            String authToken = header.replace(JwtConstant.BEARER, "");
            Claims claims = jwtTokenUtil.getJwtClaims(authToken);

            String username = claims.getSubject();

            UserDetails userDetails = userDetailsService.loadUserByUsername(username);
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails,
                    "", getAuthoritiesFromString(claims));

            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

            logger.info("authenticated user " + username + ", setting security context");
            SecurityContextHolder.getContext().setAuthentication(authentication);

        }

        filterChain.doFilter(request, response);
    }

    private Collection<? extends GrantedAuthority> getAuthoritiesFromString(Claims claims) {

        return Arrays.stream(claims.get(JwtConstant.AUTHORITIES).toString().split(",")).map(SimpleGrantedAuthority::new)
                .collect(Collectors.toList());
    }

}
public Claims getJwtClaims(String token) {

        Claims claims = null;

        try {
            claims = Jwts.parserBuilder().setSigningKey(getPublicKey()).build().parseClaimsJws(token).getBody();
        } catch (ExpiredJwtException e) {
            throw new CustomException(env.getProperty(ExceptionMessage.TOKEN_EXPIRED),e, ErrorCode.TOKEN_EXPIRE);
        } catch (SignatureException | MalformedJwtException e) {
            throw new CustomException(env.getProperty(ExceptionMessage.TOKEN_INVALID),e, ErrorCode.TOKEN_INVALID);
        } catch (Exception e) {
            throw new CustomException(env.getProperty(ExceptionMessage.TOKEN_PARSING),e, ErrorCode.INTERNAL_SERVER_ERROR);
        }

        return claims;
    } 
{
    "timestamp": "2020-11-30T08:28:40.319+00:00",
    "status": 500,
    "error": "Internal Server Error",
    "message": "Token Expired",
    "path": "/api/users/profile"
}

我想要以下异常响应,这是我的自定义响应类:

{
    "message": "Token Expired",
    "code": 101,
    "error": true,
    "timestamp": "2020-11-30T08:31:46.911+00:00"
}

共有1个答案

漆雕嘉茂
2023-03-14

为“/error”创建customerErrorController,如下所示:

@RestController
public class CustomErrorController implements ErrorController {
    
    private static final String PATH = "/error";
    
    @RequestMapping(PATH)
    public ResponseEntity<ErrorDetails> handleError(final HttpServletRequest request,
            final HttpServletResponse response) throws Throwable {
        throw (Throwable) request.getAttribute("javax.servlet.error.exception");
    }
    
    @Override
    public String getErrorPath() {
        return PATH;
    }
}

然后@RestControllerAdvise将能够选择异常。

 类似资料:
  • 我正在编写一个程序,它使用了带有Spring Security的JWT身份验证。我已经实现了自定义授权和身份验证过滤器。另外,我需要持久化我的令牌,它是由这些过滤器形成的。为此,我创建了令牌DAO服务,它自动连接到过滤器,并用注释标记我的过滤器以自动连接该服务。但我无法正确自动执行身份验证管理器。 我尝试在安全配置类中公开身份验证管理器bean,但没有结果。 这个错误是我在尝试构建项目时遇到的。

  • 注意:我的问题与Spring-Boot REST API+web应用程序的安全性有关。

  • 我在后端的一个spring引导应用程序中工作,我想使用firebase来进行身份验证过程。我在我的spring启动项目中正确地设置了firebase,并在以下开源存储库中添加了安全层:https://github.com/savicprvoslav/spring-boot-starter 因为Firebase令牌的生存期为1小时,所以当Firebase SDK抛出FireBaseAuthExcep

  • 我正在开发一个具有自己的身份验证和授权机制的REST应用程序。我想使用JSON Web Tokens进行身份验证。以下是有效且安全的实现吗? < li >将开发一个REST API来接受用户名和密码并进行认证。要使用的HTTP方法是POST,因此没有缓存。此外,在传输时还会有安全SSL < li >在认证时,将创建两个JWTs访问令牌和刷新令牌。刷新令牌将具有更长的有效期。这两个令牌都将写入coo

  • 我想添加用户的ID作为自定义声明到我的令牌。 但我无法在过滤器中获取用户id,因为依赖注入在过滤器中不起作用。我尝试使用UserService的构造函数,但在这个服务中,我有一个存储库,它是im@Autowiring,所以在调试模式下,我看到userRepository字段为空。 我的问题是我将如何添加这个自定义声明?也许这是添加这个的另一种方式。 我正在学习本教程(没有“旁白”章节)https: