SpringBoot Security-总是收到错误的凭证

时间:2018-09-02 16:56:07

标签: java mysql spring-boot spring-security jwt

我已经调试了10个小时,似乎无法弄清楚为什么我在Spring Security中不断收到错误的凭证错误。

实际上,我可以看到我正在从userdetailsservice的数据库中捕获用户。密码正确匹配(当前不对任何东西进行哈希/编码),但是当我进入框架时,会出现不匹配凭据异常。

说实话,我没有主意,我觉得我现在已经重写了3-4次此代码,但无济于事。

我要点击/login来生成令牌。

Jwt安全配置

import com.schachte.asciiphile.security.messaging.JwtAuthenticationEntryPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
@Configuration
@Order(1)
public class JwtSecurityConfig extends WebSecurityConfigurerAdapter {

    private static final String ROOT_CTX_MATCH_PATH = "/phile/**";

    @Autowired
    private JwtAuthenticationEntryPoint entryPoint;

    @Qualifier("userDetailsServiceImpl")
    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        http.addFilterBefore(new JwtLoginFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class);
        http.headers().cacheControl();
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }
}

Jwt登录过滤器

import com.fasterxml.jackson.databind.ObjectMapper;
import com.schachte.asciiphile.model.JwtAuthententicationToken;
import com.schachte.asciiphile.model.User;
import com.schachte.asciiphile.security.util.JwtGenerator;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.auth0.jwt.JWT;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import static com.auth0.jwt.algorithms.Algorithm.HMAC512;
import java.io.IOException;
import java.util.Date;
import java.util.List;

public class JwtLoginFilter extends UsernamePasswordAuthenticationFilter {

    private JwtGenerator jwtGenerator = new JwtGenerator();

    private AuthenticationManager authenticationManager;

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

    @Override
    public Authentication attemptAuthentication(
            HttpServletRequest req, HttpServletResponse res)
            throws AuthenticationException {

        User creds = null;
        try {
            creds = new ObjectMapper()
                    .readValue(req.getInputStream(), User.class);
        } catch (IOException e) {
            e.printStackTrace();
        }

        List<GrantedAuthority> grantedAuthorities = AuthorityUtils
                .commaSeparatedStringToAuthorityList(creds.getRole());

        return authenticationManager.authenticate(
                new JwtAuthententicationToken(
                        creds.getUsername(),
                        creds.getPassword(),
                        grantedAuthorities
                )
        );
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication auth) throws IOException, ServletException {
        super.successfulAuthentication(request, response, chain, auth);
        String token = JWT.create()
                .withSubject(((User) auth.getPrincipal()).getUsername())
                .withExpiresAt(new Date(System.currentTimeMillis() + 864_000_000))
                .sign(HMAC512("secret".getBytes()));
        response.addHeader("Authorization", "Token " + token);
    }
}

Jwt身份验证令牌

import lombok.Data;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;

import java.util.List;

@Data
public class JwtAuthententicationToken extends UsernamePasswordAuthenticationToken {

    private String username;
    private String password;
    private List<GrantedAuthority> grantedAuthorities;

    public JwtAuthententicationToken(String username, String password, List<GrantedAuthority> grantedAuthorities) {
        super(null, null);
        this.username = username;
        this.password = password;
        this.grantedAuthorities = grantedAuthorities;
    }

    @Override
    public Object getCredentials() {
        return null;
    }

    @Override
    public Object getPrincipal() {
        return this.username;
    }
}

自定义用户详细信息

import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

public class CustomUserDetails extends User implements UserDetails {
  private Collection<? extends GrantedAuthority> authorities;

  public CustomUserDetails(final User user, Collection<? extends GrantedAuthority> authorities) {
    super(user);
    this.authorities = authorities;
  }

  @Override
  public Collection<? extends GrantedAuthority> getAuthorities() {
    return authorities;
  }

  @Override
  public String getUsername() {
    return super.getUsername();
  }

  @Override
  public String getPassword() {
    return super.getPassword();
  }

  @Override
  public boolean isAccountNonExpired() {
    return true;
  }

  @Override
  public boolean isAccountNonLocked() {
    return true;
  }

  @Override
  public boolean isCredentialsNonExpired() {
    return true;
  }

  @Override
  public boolean isEnabled() {
    return true;
  }
}

用户

import javax.persistence.*;
import lombok.Data;

@Entity
@Data
public class User {

  public User() {}

  public User(String username, String pass, String role) {
    this.username = username;
    this.password = pass;
    this.role = role;
  }

  public User(User username) {
    this.email = username.getEmail();
    this.password = username.getPassword();
    this.premium = username.getPremium();
    this.storedBytes = username.getStoredBytes();
    this.username = username.getUsername();
  }

  @Id
  @Column(name = "username")
  private String username;

  @Column(name = "password")
  private String password;

  @Column(name = "email")
  private String email;

  @Column(name = "premium")
  private int premium;

  @Column(name = "storedbytes")
  private int storedBytes;

  @Column(name = "role")
  private String role;
}

用户详细信息服务

import com.schachte.asciiphile.model.CustomUserDetails;
import com.schachte.asciiphile.model.User;
import com.schachte.asciiphile.repository.UserRepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.Optional;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserRepo applicationUserRepository;

    public UserDetailsServiceImpl(UserRepo applicationUserRepository) {
        this.applicationUserRepository = applicationUserRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Optional<User> applicationUser = applicationUserRepository.findByUsername(username);
        if (!applicationUser.isPresent()) {
            throw new UsernameNotFoundException(username);
        }
        return new CustomUserDetails(applicationUser.get(), AuthorityUtils
                .commaSeparatedStringToAuthorityList(applicationUser.get().getRole()));
    }
}

0 个答案:

没有答案