API

时间:2016-05-13 18:06:42

标签: spring authentication spring-security spring-boot

我一直在网上搜索使用Spring& amp;和许多不同的方法来实现基于令牌的身份验证。 Spring Security(SS)。我真的不想在Oauth路线上全力以赴,所以我一直在尝试做一些事情并保持简单。

我想要的是将用户名/密码传递给SS的内置机制,并在成功时生成一个我传回用户的令牌。然后,用户在自定义标头中使用令牌进行所有将来的请求。令牌将在som长度之后到期。我知道这是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);
    }
}

为了查看令牌的标题并告诉spring一切顺利,我创建了一个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只是让一切都通过。

1 个答案:

答案 0 :(得分:3)

好吧,经过多次试验和错误之后,只需将以下内容添加到我的JavaScript Dependency Injection

即可

SpringSecurityConfig

有点惊讶我没有早点碰到这个。不确定这是否有点新鲜或什么。