简体   繁体   English

JWT authentication with spring and angular with null header

[英]JWT authentication with spring and angular with null header

I am trying to do JWT token authentication using spring boot and angular.我正在尝试使用 spring 引导和 angular 进行 JWT 令牌身份验证。 After login bearer token is created but after that in JWTAuthorizationFilter i am getting null header and because of that it return anonymousUser.创建登录不记名令牌后,但在JWTAuthorizationFilter中创建后,我得到 null header 并因此返回匿名用户。 Please tell me why i am getting null header.请告诉我为什么我得到 null header。

SecurityConfig.java安全配置.java

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;
    
    @Autowired
    private CustomUserDetailService customUserDetailService;
     
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception { 
         http.
         cors().configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues())
        .and().csrf().disable()
                .authorizeRequests()                                                                
                .antMatchers("/**").permitAll()                  
                .antMatchers("/manage/**").hasRole("ADMIN")                                      
                .antMatchers("/").hasRole("USER")
                .and()
                .exceptionHandling()
                .accessDeniedPage("/access-denied")
                .and()
                .addFilter(new JWTAuthenticationFilter(authenticationManager()))
                .addFilter(new JWTAuthorizationFilter(authenticationManager(), customUserDetailService));
    }
     
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserDetailService).passwordEncoder(new 
   
        BCryptPasswordEncoder());
    }
}

JWTAuthenticationFilter.java JWTAuthenticationFilter.java

    public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    private AuthenticationManager authenticationManager;

    public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        try {
            UserDetail user = new ObjectMapper().readValue(request.getInputStream(), UserDetail.class);
            return this.authenticationManager
                    .authenticate(new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword()));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request,
                                            HttpServletResponse response,
                                            FilterChain chain,
                                            Authentication authResult) throws IOException, ServletException {
        String username = ((org.springframework.security.core.userdetails.User) authResult.getPrincipal()).getUsername();
        String token = Jwts
                .builder()
                .setSubject(username)
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                .signWith(SignatureAlgorithm.HS512, SECRET)
                .compact();
        String bearerToken = TOKEN_PREFIX + token;
        System.out.println(bearerToken);
        response.getWriter().write(bearerToken);
        response.addHeader(HEADER_STRING, bearerToken);
       }
    }

JWTAuthorizationFilter.java JWTAuthorizationFilter.java

    public class JWTAuthorizationFilter extends BasicAuthenticationFilter {
    private final CustomUserDetailService customUserDetailService;

    public JWTAuthorizationFilter(AuthenticationManager authenticationManager, CustomUserDetailService customUserDetailService) {
        super(authenticationManager);
        this.customUserDetailService = customUserDetailService;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain chain) throws IOException, ServletException {
        String header = request.getHeader(HEADER_STRING);
        if (header == null || !header.startsWith(TOKEN_PREFIX)) {
            chain.doFilter(request, response);
            return;
        }
        UsernamePasswordAuthenticationToken authenticationToken = getAuthenticationToken(request);
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        chain.doFilter(request, response);
    }

    private UsernamePasswordAuthenticationToken getAuthenticationToken(HttpServletRequest request) {
        String token = request.getHeader(HEADER_STRING);
        if (token == null) return null;
        String username = Jwts.parser().setSigningKey(SECRET)
                .parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
                .getBody()
                .getSubject();
        UserDetails userDetails = customUserDetailService.loadUserByUsername(username);
        return username != null ?
                new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()) 
      : null;
      }
      }

CustomUserDetailService.java CustomUserDetailService.java

@Component
public class CustomUserDetailService implements UserDetailsService {

    private List<GrantedAuthority> role;

    @Autowired
    private UserDAO userDAO;

    /*
     * @Autowired public CustomUserDetailService(UserRepository userRepository) {
     * this.userRepository = userRepository; }
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        User user = Optional.ofNullable(userDAO.getByEmail(username))
                .orElseThrow(() -> new UsernameNotFoundException("User not found"));
        List<GrantedAuthority> authorityListAdmin = AuthorityUtils.createAuthorityList("ROLE_ADMIN");
        List<GrantedAuthority> authorityListUser = AuthorityUtils.createAuthorityList("ROLE_USER");
        if (user.getRole() == "admin") {
            role = authorityListAdmin;
        } else {
            role = authorityListUser;
        }
        return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(), role);
    }
}

Userinfo.java用户信息.java

private String email;
private String role;
private String password;

Controller Controller

@RequestMapping(value = "/login")
public ModelAndView login(
        @RequestParam(name = "error", required = false) String error,
        @RequestParam(name = "logout", required = false) String logout,
        HttpServletRequest request,
        HttpServletResponse response) {

    ModelAndView mv = new ModelAndView("login");
    HttpSession session= request.getSession(false);
    Authentication auth = SecurityContextHolder.getContext()
        .getAuthentication();
      
    System.out.println("auth ===" + auth);
    System.out.println("logout ===" + logout);
 
    return mv; 
}

This is the output on console:这是控制台上的 output:

 

 Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJidW50QGdtYWlsLmNvbSIsImV4cCI6MTU5NjExMjcwM30.fBFMDO--8Q_56LT_qbioiT6p3BOxk3L9OrPVTw5EGbf7oJ0ky7W7PuahIYcdjYSL6-OsHY6qq8tPEetlJO7nEg

auth ===org.springframework.security.authentication.AnonymousAuthenticationToken@823df96a: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS

Please tell me what i am missing here.请告诉我我在这里缺少什么。

Your JWTAuthenticationFilter that extends UsernamePasswordAuthenticationFilter overrides successfulAuthentication method which by default calls this line:您的JWTAuthenticationFilter扩展UsernamePasswordAuthenticationFilter覆盖successfulAuthentication方法,默认情况下调用此行:

SecurityContextHolder.getContext().setAuthentication(authResult);

Your implementation do not have this line so after processing of this filter you still do not have Authentication in Spring context.您的实现没有此行,因此在处理此过滤器后,您在 Spring 上下文中仍然没有Authentication The next filter that is called is your JWTAuthorizationFilter which tries to read header from same request object as in previous filter.调用的下一个过滤器是您的JWTAuthorizationFilter ,它尝试从与前一个过滤器相同的request object 中读取 header。 JWTAuthenticationFilter sets this header in response object not in request object. JWTAuthenticationFilter设置此 header 以response object 不在request object 中。 So basically you ends up without authentication because if (header == null ||.header.startsWith(TOKEN_PREFIX)) is always true after login flow.因此,基本上您最终没有进行身份验证,因为if (header == null ||.header.startsWith(TOKEN_PREFIX))在登录流程后始终为真。

First thing, in the authentication filter token generated and set on the HttpServletResponse header not on the request object's header.首先,在 HttpServletResponse header 上生成和设置的身份验证过滤器令牌中,而不是在请求对象的 header 上。 Then next the authorization filter checking the request header for token, so there may be the issue of null happened.然后授权过滤器检查请求 header 以获得令牌,因此可能发生了null的问题。

Usually authentication and authorization will not be chained like this, but don't know regarding the actual use case you were trying to implement.通常身份验证和授权不会像这样链接,但不知道您尝试实现的实际用例。

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

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