无法使用JWT身份验证机制登录

时间:2018-11-13 06:18:51

标签: java rest spring-boot authentication jwt

我正在使用Spring Web,Spring Security开发SpringBoot 2.0应用程序,并使用JWT进行身份验证。只有1个URI路径是公共的,任何人都可以访问,除了所有其他URI被保护并在任何尝试期间抛出“访问被拒绝”之外。我可以访问此公共URI,并使用用户名和密码在数据库中创建一个新用户。但是,当我尝试使用相同的凭据登录时,出现HTTP 403 Forbidden错误。

请在这里帮助我。谢谢

身份验证类别:-

public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    private static Logger logger = LoggerFactory.getLogger(JWTAuthenticationFilter.class);

    private AuthenticationManager authenticationManager;

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

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request,
                                                HttpServletResponse response) throws AuthenticationException {
        logger.info("Entering attemptAuthentication@JWTAuthenticationFilter");

        try{
            ApplicationUser credential = new ObjectMapper()
                    .readValue(request.getInputStream(), ApplicationUser.class);
            logger.info("Validating Credential:: {}, {}", credential.getUsername(), credential.getPassword());

            return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(credential.getUsername(),
                            credential.getPassword(), new ArrayList<>()));

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

    @Override
    protected void successfulAuthentication(HttpServletRequest request,
                                            HttpServletResponse response,
                                            FilterChain chain, Authentication authResult)
            throws IOException, ServletException {
        logger.info("Entering successfulAuthentication@JWTAuthenticationFilter");

        String jwtToken = Jwts.builder()
                .setSubject(((User) authResult.getPrincipal()).getUsername())
                .setExpiration(new Date(System.currentTimeMillis() + SecurityConstant.EXPIRATION_TIME))
                .signWith(SignatureAlgorithm.HS512, SecurityConstant.SECRET)
                .compact();

        logger.info("JWT Token:: {}", jwtToken);
        response.addHeader(SecurityConstant.HEADER_STRING, SecurityConstant.TOKEN_PREFIX + jwtToken);

    }

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                                              AuthenticationException failed) throws IOException, ServletException {
        logger.info("Failed authentication while attempting to access");
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failed");
    }
}

授权等级:-

public class JWTAuthorizationFilter extends BasicAuthenticationFilter {
    private static Logger logger = LoggerFactory.getLogger(JWTAuthorizationFilter.class);

    public JWTAuthorizationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }


    /**
     *
     * @param request
     * @param response
     * @param chain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain chain) throws IOException, ServletException {
        logger.info("Entering doFilterInternal@JWTAuthorizationFilter");

        String header = request.getHeader(SecurityConstant.HEADER_STRING);
        logger.info("header:: {}", header);

        if(null == header || !header.startsWith(SecurityConstant.TOKEN_PREFIX)){
            logger.info("chaining");
            chain.doFilter(request, response);
            return;
        }

        UsernamePasswordAuthenticationToken authentication = getAuthentication(header);
        logger.info("Authentication:: {}", authentication);

        SecurityContextHolder.getContext().setAuthentication(authentication);
        chain.doFilter(request, response);

    }


    /**
     *
     * @param header
     * @return
     */
    private UsernamePasswordAuthenticationToken getAuthentication(String header){
        logger.info("Entering getAuthenticationToken@JWTAuthorizationFilter");
        logger.info("token::{}", header);
        if(null != header){

            //Parsing JWT Token
            String user = Jwts.parser()
                    .setSigningKey(SecurityConstant.SECRET)
                    .parseClaimsJws(header.replace(SecurityConstant.TOKEN_PREFIX, ""))
                    .getBody()
                    .getSubject();

            logger.info("user:: {}",user);
            if(null != user){
                return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
            }
            return null;
        }
            return null;
    }
}

WebSecurity类:-

@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {

    private UserDetailsService userDetailsService;

    private BCryptPasswordEncoder bCryptPasswordEncoder;


    public WebSecurity(UserDetailsService userDetailsService,
                       BCryptPasswordEncoder bCryptPasswordEncoder) {
        this.userDetailsService = userDetailsService;
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
       auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
                 http.cors().and().csrf()
                .disable()
                .authorizeRequests()
                .antMatchers(HttpMethod.POST, SecurityConstant.SIGN_UP_URL).permitAll()
                .anyRequest().authenticated()
                .and()
                .addFilter(new JWTAuthenticationFilter(authenticationManager()))
                .addFilter(new JWTAuthorizationFilter(authenticationManager()))

                // this disables session creation on Spring Security
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
        return source;
    }
}

Application.properties文件:-

#spring.security.user.name=user
#spring.security.user.password=user

spring.data.mongodb.uri=mongodb://localhost:27017/myspringdb

用于注册的PostMan测试数据(正在运行):-

http://localhost:8080/users/sign-up

{
  "id":"2",
  "username":"user",
  "password":"user",
  "emailAddress":"abc@sample.com"
}

用于登录的PostMan测试数据(不起作用):-

http://localhost:8080/login

标题:content-type:application / json

{
  "username":"user",
  "password":"user"
}

并且还想知道Im是否可以通过使用spring-security来解决问题,因为在运行程序时,程序会自行生成密码,如下所示:-

使用生成的安全密码:ki908a3f-00ec-98cc-bn02-823ead10f153

我应该使用保存在数据库(mongodb)中的我自己的凭据还是今年春天生成的用于身份验证的密码?

谢谢

0 个答案:

没有答案