简体   繁体   English

JwtUsernameAndPasswordAuthenticationFilter 在这个例子中是如何工作的?

[英]How does JwtUsernameAndPasswordAuthenticationFilter work in this example?

Below is my example of Configuration, as far as I understand, JwtUsernameAndPasswordAuthenticationFilter works first ( it gets username, password from request, checks if they are correct and provides a token ), then - JwtTokenVerifier.下面是我的配置示例,据我所知,JwtUsernameAndPasswordAuthenticationFilter 首先工作(它从请求中获取用户名、密码,检查它们是否正确并提供令牌),然后 - JwtTokenVerifier。

I have a few questions:我有几个问题:

  1. Is JwtUsernameAndPasswordAuthenticationFilter checks requests every time for containing username and password? JwtUsernameAndPasswordAuthenticationFilter 是否每次都检查包含用户名和密码的请求? If not, when does it check it?如果没有,它什么时候检查它? Once per what?一次什么?

  2. Why do we create Authentication object in JwtTokenVerifier class with no password ( just username and Authorities ) and put it in Context?为什么我们在 JwtTokenVerifier 类中创建没有密码(只有 username 和 Authorities )的 Authentication 对象并将其放在 Context 中?

PS I do appreciate your answers! PS我非常感谢你的回答! And know how dumb the question may seems to be.并且知道这个问题看起来有多么愚蠢。

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .addFilter(new JwtUsernameAndPasswordAuthenticationFilter(authenticationManager(), jwtConfig, secretKey))
                .addFilterAfter(new JwtTokenVerifier(secretKey, jwtConfig),JwtUsernameAndPasswordAuthenticationFilter.class)
                .authorizeRequests()
                .antMatchers("/", "index", "/css/*", "/js/*").permitAll()
                .antMatchers("/api/**").hasRole(STUDENT.name())
                .anyRequest()
                .authenticated();
    }


public class JwtUsernameAndPasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    private final AuthenticationManager authenticationManager;
    private final JwtConfig jwtConfig;
    private final SecretKey secretKey;

    public JwtUsernameAndPasswordAuthenticationFilter(AuthenticationManager authenticationManager,
                                                      JwtConfig jwtConfig,
                                                      SecretKey secretKey) {
        this.authenticationManager = authenticationManager;
        this.jwtConfig = jwtConfig;
        this.secretKey = secretKey;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request,
                                                HttpServletResponse response) throws AuthenticationException {

        try {
            UsernameAndPasswordAuthenticationRequest authenticationRequest = new ObjectMapper()
                    .readValue(request.getInputStream(), UsernameAndPasswordAuthenticationRequest.class);

            Authentication authentication = new UsernamePasswordAuthenticationToken(
                    authenticationRequest.getUsername(),
                    authenticationRequest.getPassword()
            );

            Authentication authenticate = authenticationManager.authenticate(authentication);
            return authenticate;

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request,
                                            HttpServletResponse response,
                                            FilterChain chain,
                                            Authentication authResult) throws IOException, ServletException {
        String token = Jwts.builder()
                .setSubject(authResult.getName())
                .claim("authorities", authResult.getAuthorities())
                .setIssuedAt(new Date())
                .setExpiration(java.sql.Date.valueOf(LocalDate.now().plusDays(jwtConfig.getTokenExpirationAfterDays())))
                .signWith(secretKey)
                .compact();

        response.addHeader(jwtConfig.getAuthorizationHeader(), jwtConfig.getTokenPrefix() + token);
    }
}

public class JwtTokenVerifier extends OncePerRequestFilter {

private final SecretKey secretKey;
private final JwtConfig jwtConfig;

public JwtTokenVerifier(SecretKey secretKey,
                        JwtConfig jwtConfig) {
    this.secretKey = secretKey;
    this.jwtConfig = jwtConfig;
}

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

    String authorizationHeader = request.getHeader(jwtConfig.getAuthorizationHeader());

    if (Strings.isNullOrEmpty(authorizationHeader) || !authorizationHeader.startsWith(jwtConfig.getTokenPrefix())) {
        filterChain.doFilter(request, response);
        return;
    }

    String token = authorizationHeader.replace(jwtConfig.getTokenPrefix(), "");

    try {

        Jws<Claims> claimsJws = Jwts.parser()
                .setSigningKey(secretKey)
                .parseClaimsJws(token);

        Claims body = claimsJws.getBody();

        String username = body.getSubject();

        var authorities = (List<Map<String, String>>) body.get("authorities");

        Set<SimpleGrantedAuthority> simpleGrantedAuthorities = authorities.stream()
                .map(m -> new SimpleGrantedAuthority(m.get("authority")))
                .collect(Collectors.toSet());

        Authentication authentication = new UsernamePasswordAuthenticationToken(
                username,
                null,
                simpleGrantedAuthorities
        );

        SecurityContextHolder.getContext().setAuthentication(authentication);

    } catch (JwtException e) {
        throw new IllegalStateException(String.format("Token %s cannot be trusted", token));
    }

    filterChain.doFilter(request, response);
}

} }

  1. JwtUsernameAndPasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter , and by default its triggered when you make a "POST" call to "/login". JwtUsernameAndPasswordAuthenticationFilter扩展了UsernamePasswordAuthenticationFilter ,默认情况下它会在您对“/login”进行“POST”调用时触发。 This can be changed by calling the setFilterProcessesUrl(<PATH_HERE>) in the JwtUsernameAndPasswordAuthenticationFilter 's constructor.这可以通过调用JwtUsernameAndPasswordAuthenticationFilter的构造函数中的setFilterProcessesUrl(<PATH_HERE>)来更改。

  2. You don't keep the password in the Authentication object simply because it's not needed, and it's safer to keep the password off-memory because anyone with access to the memory dump can retrieve the password.您不会仅仅因为不需要密码而将密码保存在 Authentication 对象中,并且将密码保存在内存外更安全,因为任何有权访问内存转储的人都可以检索密码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM