我已经调试了10个小时,似乎无法弄清楚为什么我在Spring Security中不断收到错误的凭证错误。
实际上,我可以看到我正在从userdetailsservice
的数据库中捕获用户。密码正确匹配(当前不对任何东西进行哈希/编码),但是当我进入框架时,会出现不匹配凭据异常。
说实话,我没有主意,我觉得我现在已经重写了3-4次此代码,但无济于事。
我要点击/login
来生成令牌。
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);
}
}
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);
}
}
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()));
}
}