2016-05-13 64 views
2

我一直在網上衝浪,看看許多不同的方式來實現基於令牌的認證使用春季&春季安全(SS)。我並不是真的想要在Oauth路線上全力以赴,所以我一直在努力做一些事情,讓事情變得非常簡單。春季安全和令牌認證的API

我想要的是將用戶名/密碼傳遞給SS的內置機制,並在成功時生成令牌並將其傳回給用戶。然後,用戶使用自定義標題中的令牌進行所有未來的請求。令牌將在很長時間後過期。我知道這是Oauth所做的,但又不想使用它。

所以我有一些工作。我可以用用戶名/密碼登錄並取回令牌。然後,我可以成功地用令牌發出請求。什麼是不工作是權威。下面是我在做什麼...

  • 自定義驗證失敗處理器簡單地返回HttpServletResponse.SC_UNAUTHORIZED
  • 定製成功處理程序簡單地返回HttpServletResponse.SC_OK和令牌
  • 自定義驗證入口點只是HttpServletResponse.SC_UNAUTHORIZED
  • 應答

現在,我也有一個自定義UserDetails和UserDetailsS​​ervice。

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

    } 
} 

這就是我是如何配置的Web安全:

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

那種我沒有碰到這個越快。不知道這是否有點新或什麼。