Ich habe das Web auf der Suche nach einer Vielzahl von Möglichkeiten, Token-basierte Authentifizierung mit Spring Spring Safety (SS) Spring & zu implementieren. Ich möchte nicht wirklich auf der Oauth-Route fahren, also habe ich versucht, etwas zu machen und die Dinge ziemlich einfach zu halten.Spring Security und Token Auth für API
Ich möchte einen Benutzernamen/ein Passwort an den integrierten Mechanismus von SS übergeben und bei Erfolg ein Token generieren, das ich an den Benutzer zurückgebe. Der Benutzer nimmt dann alle zukünftigen Anfragen mit dem Token in einem benutzerdefinierten Header vor. Das Token wird nach einiger Zeit ablaufen. Ich bin mir bewusst, dass dies etwas ist, was Oauth tut, aber ich möchte es nicht benutzen.
So habe ich etwas arbeiten. Ich kann mich mit Benutzername/Passwort einloggen und das Token zurückbekommen. Ich kann dann Anfragen mit dem Token erfolgreich machen. Was nicht funktioniert, sind Behörden. Hier ist, was ich tue ...
- Benutzerdefinierte Auth Failure Handler, die einfach zurückgibt
HttpServletResponse.SC_UNAUTHORIZED
- Benutzerdefinierte Erfolg Handler, die einfach zurückgibt
HttpServletResponse.SC_OK
und das Token - Benutzerdefinierte Auth Einspeisepunkt, die gerade Antwort mit
HttpServletResponse.SC_UNAUTHORIZED
Jetzt habe ich auch eine benutzerdefinierte UserDetails und UserDetailsService.
public class MyUserDetails implements UserDetails {
private User user; // this is my own User object
private List<GrantedAuthority> authorities;
public MyUserDetails(User user, List<GrantedAuthority> authorities) {
this.user = user;
this.authorities = authorities;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public void setAuthorities(List<GrantedAuthority> authorities) {
this.authorities = authorities;
}
}
@Service
public class MyUserDetailsService implements UserDetailsService {
private final UserService userService;
@Autowired
public MyUserDetailsService(UserService userService) {
this.userService = userService;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userService.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException(username);
}
List<GrantedAuthority> authorities = new ArrayList<>();
// for now, just add something
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
return new MyUserDetails(user, authorities);
}
}
Um im Header für das Token zu suchen und Feder zu sagen, alles ist gut, ich AuthTokenFilter erstellt ...
public class AuthTokenFilter extends UsernamePasswordAuthenticationFilter {
@Autowired
private MyUserDetailsService userDetailsService;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String authToken = httpRequest.getHeader("X-TOKEN-AUTH");
String username = null;
if (authToken != null) {
username = Jwts.parser()
.setSigningKey("1234")
.parseClaimsJws(authToken)
.getBody()
.getSubject();
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
// TODO: validate token
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
chain.doFilter(request, response);
}
}
Und das ist, wie ich Web-Sicherheit konfiguriert haben:
Alles scheint zu funktionieren, SS ist nicht den Zugriff überhaupt zu begrenzen. Wenn der Token da ist, lässt SS einfach alles passieren.