将自定义身份验证包装到Spring安全性中的最简单方法是什么?

时间:2015-12-26 12:28:03

标签: java spring authentication spring-security

假设我有简单的bean,它可以通过密码验证用户,也知道任何指定用户的角色:

interface MyBeanInterface {
    boolean check(String username, String password);
    List<String> roles(String username);
}

使用基本HTTP安全性将此功能插入Spring Web应用程序的最简单方法是什么?

同时,我想仅使用@Secured注释来注释我的控制器和服务方法。请没有任何以点分隔的谓词like here

我无法在Spring Security API中突破众多“populator”,“manager”,“adapter”和其他“configurers”...

更新

我写道:

1)从控制器返回的Greeting

2)用于投放网络请求GreetingController/greeting1的{​​{1}}课程。我使用/greeting2注释第一个方法,使用@Secured({"USER", "ADMIN"})注释第二个方法。

3)我写了@Secured({"ADMIN"})我在其中验证了两个具有不同访问级别的用户。

4)我写了MyAuthService,其中实现了AuthenticationProviderEx方法,调用了authenticate() bean。

5)我写了MyAuthService bean,SecurityConfig返回我的提供者。

代码为here in commit fdc2466。在这种状态下,它根本不会要求身份验证。

更新2

我已将configure()添加到@EnableGlobalMethodSecurity(securedEnabled = true)类,但它开始询问用户名和密码,但遗憾的是,在任何请求中都会返回错误SecurityConfig

2 个答案:

答案 0 :(得分:2)

在您的界面周围创建一个自定义身份验证提供程序包装器,如:

@Component("customAuthenticationProvider")
public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private MyBeanInterface myInterface;

    public Authentication authenticate(Authentication authentication) {
        String username = authentication.getName();
        String password = authentication.getCredentials().toString();
        if (!myInterface.check(username, password)) {
            throw new BadCredentialsException("Bad username or password.");
        }
        List<GrantedAuthority> authorities = new ArrayList<>();
        for (String role : myInterface.roles(username)) {
            authorities.add(new SimpleGrantedAuthority(role));
        }
        return new UsernamePasswordAuthenticationToken(username, password, authorities);
    }

    public boolean supports(Class<?> clazz) {
        return UsernamePasswordAuthenticationToken.class.equals(clazz);
    }

}

使用XML:

在安全配置中使用它
<authentication-manager>
  <authentication-provider ref="customAuthenticationProvider"/>
</authentication-manager>

更新:也适用于java配置:

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomAuthenticationProvider customAuthenticationProvider;

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

    /* rest of security config here */
}

其余的都很正常。

答案 1 :(得分:1)

添加如下的java配置:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {  
    @Autowired YourAuthFilter youfilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .addFilterBefore(yourfilter, UsernamePasswordAuthenticationFilter.class);
    }
}

YourAuthFilter会是这样的:

@Component
public class YourAuthFilter extends GenericFilterBean {
    @Autowired private MyBeanInterface myBeanInterface;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // extract http basic tokens
        // use your myBeanInterface to authenticate
        // if it was successful, set Authentication 
        // by using SecurityContextHolder.getContext().setAuthentication(...)
        // otherwise, do whatever suits your application needs
        chain.doFilter(request, response);
    }
}

holmis83方法要好得多,但如果你想在Java Config中使用它:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired CustomAuthenticationProvider customAuthenticationProvider;

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .httpBasic();
    }
}