Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
验证用户时的无限循环:使用Spring安全性实现JWT_Spring_Spring Boot_Jwt - Fatal编程技术网

验证用户时的无限循环:使用Spring安全性实现JWT

验证用户时的无限循环:使用Spring安全性实现JWT,spring,spring-boot,jwt,Spring,Spring Boot,Jwt,编辑:除注册和登录外,我现在收到403禁止访问、拒绝访问的请求 在基于本文实现了JWT身份验证和spring安全性之后,我正在测试我的应用程序端点: 同样,我的其他灵感来源包括: 用户的注册和登录是功能性的,但是当我执行后续请求时需要在头中使用JWT,我会得到一个无限循环/递归和一个堆栈溢出错误。然而,当我故意输入一个不存在的JWT时,它会抛出相应的错误消息,并且运行良好。因此,问题在于成功验证有效的JWT。在线查看不同的堆栈溢出答案后,如: 它们似乎都说了同样的话,ProviderManag

编辑:除注册和登录外,我现在收到403禁止访问、拒绝访问的请求

在基于本文实现了JWT身份验证和spring安全性之后,我正在测试我的应用程序端点:

同样,我的其他灵感来源包括:

用户的注册和登录是功能性的,但是当我执行后续请求时需要在头中使用JWT,我会得到一个无限循环/递归和一个堆栈溢出错误。然而,当我故意输入一个不存在的JWT时,它会抛出相应的错误消息,并且运行良好。因此,问题在于成功验证有效的JWT。在线查看不同的堆栈溢出答案后,如:

它们似乎都说了同样的话,ProviderManager类正在查看身份验证提供程序列表,以找到一个可以对给定身份验证进行身份验证的提供程序,但没有找到,这导致了此错误,它们建议实现您自己的身份验证提供程序。下面是我针对不同相关类的代码。注意,我没有使用userDetailsService类;相反,我有自己的UserService类,它基本上具有userDetailsService的功能,还具有特定于应用程序的代码。按照上面提到的代码示例,我也没有实现我自己的身份验证提供程序,因此我希望避免实现身份验证提供程序,因为上面提到的代码示例可以工作并且更简单

JwtProvider类

@Component
public class JwtProvider {
    @Value("${security.jwt.token.secret-key:secret}")
    private String secretKey = "secret";

    @Value("${security.jwt.token.expire-length:3600000}")
    private long validityInMilliseconds = 3600000; // 1h

    @Autowired
    private AppUserService appUserService;

    // encoding the secret used to create the signature for the JWT
    @PostConstruct
    protected void init() {
        secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes());
    }

    public String createToken(String userEmail) {
        Claims claims = Jwts.claims().setSubject(userEmail); // subject is the person who is being authenticated
        Date now = new Date();
        Date validity = new Date(now.getTime() + validityInMilliseconds);
        return Jwts.builder()//
                .setClaims(claims)//
                .setIssuedAt(now)//
                .setExpiration(validity)//
                .signWith(SignatureAlgorithm.HS256, secretKey)//
                .compact();
    }

    public Authentication getAuthentication(String token) {
        AppUser user = this.appUserService.getAppUserByEmail(getUserEmail(token));
        return new UsernamePasswordAuthenticationToken(user, "");
    }

    // get userEmail in the jwt token that we receive
    public String getUserEmail(String token) {
        return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject();
    }

    // validate a token that we have: not expired, and matches the userEmail
    public boolean validateToken(String token) {
        try {
            Jws<Claims> claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token);
            if (claims.getBody().getExpiration().before(new Date())) {
                return false;
            }
            return true;
        } catch (JwtException | IllegalArgumentException e) {
            return false;
        }
    }

}
package ca.mcgill.ecse321.petadoption.controller;

import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

// configures how we filter http requests
// specifies order of applying filters
public class JwtConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
    private JwtProvider jwtProvider;
    public JwtConfigurer(JwtProvider jwtProvider) {
        this.jwtProvider = jwtProvider;
    }
    @Override
    public void configure(HttpSecurity http) throws Exception {
        JwtFilter customFilter = new JwtFilter(jwtProvider);
        http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class); 
    }
}
// Job: intercept a request and look at the header to get the JWT
public class JwtFilter extends GenericFilterBean {
    private JwtProvider jwtProvider;

    public JwtFilter(JwtProvider jwtProvider) {
        this.jwtProvider = jwtProvider;
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) 
            throws IOException, ServletException {
        String token = resolveToken((HttpServletRequest) req);
            if (token != null && jwtProvider.validateToken(token)) { // if token is not null and it isn't expired and it is valid 
                Authentication auth = jwtProvider.getAuthentication(token); // returning the UsernamePasswordAuthenticationToken
                SecurityContextHolder.getContext().setAuthentication(auth); 
            }
        filterChain.doFilter(req, res);
    }

    public String resolveToken(HttpServletRequest req) {
        String bearerToken = req.getHeader("Authorization");
        if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7, bearerToken.length());
        }
        return null;
    }
}
安全配置器类

@Configuration
@EnableWebSecurity
public class SecurityConfigurer extends WebSecurityConfigurerAdapter {

    @Autowired
    JwtProvider jwtProvider;

    @Autowired
    AppUserService appUserService;

    // this is because we cannot perform @autowired authManager anymore cuz its only compatible w/ older Spring Boot
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .httpBasic().disable()
                .csrf().disable() // this disables cross-site request forgery where an attacker manages to get an authenticated user to perform a malicious request to his liking using diff links and such
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // tell it to use the filterChain that intercepts requests and checks the authorization header for a jwt
                .and()
                .authorizeRequests()
                .antMatchers("/login").permitAll()
                .antMatchers("/login/").permitAll()
                .antMatchers("/register").permitAll()
                .antMatchers("/register/").permitAll()
                .anyRequest().authenticated()
                .and()
                .apply(new JwtConfigurer(jwtProvider)); // this specifies to add our custom filter before the usernamepasswordauthenticationfilter
    }

}
以下是我得到的错误:

  2020-03-14 12:14:27.183 ERROR 784 --- [nio-8081-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Filter execution threw an exception] with root cause

java.lang.StackOverflowError: null
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:205) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at com.sun.proxy.$Proxy120.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:195) ~[spring-security-core-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:501) ~[spring-security-config-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at sun.reflect.GeneratedMethodAccessor107.invoke(Unknown Source) ~[na:na]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:205) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at com.sun.proxy.$Proxy120.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:195) ~[spring-security-core-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:501) ~[spring-security-config-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at sun.reflect.GeneratedMethodAccessor107.invoke(Unknown Source) ~[na:na]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:205) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at com.sun.proxy.$Proxy120.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:195) ~[spring-security-core-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:501) ~[spring-security-config-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at sun.reflect.GeneratedMethodAccessor107.invoke(Unknown Source) ~[na:na]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:205) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at com.sun.proxy.$Proxy120.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:195) ~[spring-security-core-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:501) ~[spring-security-config-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at sun.reflect.GeneratedMethodAccessor107.invoke(Unknown Source) ~[na:na]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]
我对Spring和Spring Boot比较陌生,因此非常感谢您的帮助。谢谢