2016-05-13 2 views
2

Я просматривал веб-страницы, изучая множество различных способов реализации аутентификации на токенах, используя Spring & Spring Security (SS). Я не очень хочу идти полным путем на Oauth, поэтому я пытался что-то сделать и держать вещи довольно просто.Spring Security и Token Auth для API

Что я хочу, это передать имя пользователя/пароль встроенному механизму SS и успеху, сгенерировать токен, который я передаю пользователю. Затем пользователь делает все будущие запросы с токеном в пользовательском заголовке. Срок действия токена истекает через некоторое время. Я знаю, что это то, что делает Oauth, но снова, не хотят его использовать.

Итак, у меня есть что-то вроде работы. Я могу войти с именем пользователя/паролем и вернуть токен. Затем я могу успешно выполнить запросы с токеном. То, что не работает, - это власти. Вот что я делаю ...

  • Пользовательские Auth Отказ Handler, который просто возвращает HttpServletResponse.SC_UNAUTHORIZED
  • Выборочная Успех Handler, который просто возвращает HttpServletResponse.SC_OK и лексему
  • Пользовательские идентификации точки входа, что просто ответ с HttpServletResponse.SC_UNAUTHORIZED

Теперь у меня также есть пользовательские UserDetails и 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); 
    } 
} 

Для того, чтобы посмотреть в заголовке для маркеров и сказать весной все хорошо, я создал AuthTokenFilter ...

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); 

    } 
} 

И это, как я настроил веб-безопасность:

@Configuration 
@EnableWebSecurity 
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { 

    @Autowired 
    private MyUserDetailsService userDetailsService; 

    @Autowired 
    private RestAuthEntryPoint authenticationEntryPoint; 

    @Autowired 
    private AuthSuccessHandler authSuccessHandler; 

    @Autowired 
    private AuthFailureHandler authFailureHandler; 


    @Bean 
    @Override 
    public AuthenticationManager authenticationManagerBean() throws Exception { 
     return super.authenticationManagerBean(); 
    } 

    @Bean 
    @Override 
    public UserDetailsService userDetailsServiceBean() throws Exception { 
     return super.userDetailsServiceBean(); 
    } 

    @Bean 
    public AuthenticationProvider authenticationProvider() { 
     DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(); 
     authenticationProvider.setUserDetailsService(userDetailsService); 
     authenticationProvider.setPasswordEncoder(new ShaPasswordEncoder()); 

     return authenticationProvider; 
    } 

    @Bean 
    public AuthTokenFilter authenticationTokenFilterBean() throws Exception { 
     AuthTokenFilter authenticationTokenFilter = new AuthTokenFilter(); 
     authenticationTokenFilter.setAuthenticationManager(authenticationManagerBean()); 
     return authenticationTokenFilter; 
    } 

    @Override 
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
     auth.authenticationProvider(authenticationProvider()); 
    } 

    @Override 
    protected AuthenticationManager authenticationManager() throws Exception { 
     return super.authenticationManager(); 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http.csrf().disable() 
       .authorizeRequests() 
       .antMatchers("/login").permitAll() 
       .anyRequest().authenticated() 
       .and() 
       .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
       .and() 
       .authenticationProvider(authenticationProvider()) 
       .exceptionHandling() 
       .authenticationEntryPoint(authenticationEntryPoint) 
       .and() 
       .formLogin() 
       .permitAll() 
       .loginProcessingUrl("/login") 
       .usernameParameter("username") 
       .passwordParameter("password") 
       .successHandler(authSuccessHandler) 
       .failureHandler(authFailureHandler) 
       .and() 
       .logout() 
       .permitAll() 
       .and() 
       .sessionManagement() 
       .maximumSessions(1); 

     http.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class); 

     http.authorizeRequests().anyRequest().authenticated(); 
    } 


} 

Все, кажется, работает, что SS не ограничивает доступ вообще. Если токен есть SS, все пропускает.

ответ

3

Ну, после долгих проб и ошибок, это было так просто, как добавить следующее к моей SpringSecurityConfig

@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)

Вид удивлен, что я не нарваться это раньше. Не уверен, что это что-то новое или что-то новое.

Смежные вопросы