2016-05-13 15 views
2

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.

Antwort

3

Nun, nach viel Versuch und Irrtum war es so einfach wie das Hinzufügen der folgenden meiner SpringSecurityConfig

@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)

Art überrascht, dass ich nicht in diese früher ausgeführt haben. Ich bin mir nicht sicher, ob das etwas Neues ist oder was.

Verwandte Themen