在使用纯java配置时,我花了相当多的时间在弹簧安全性上。要使其正常工作,需要执行几个步骤。它应该是沿着这些路线的东西。基本流程如下:
创建自定义筛选器以检查对特定授权信息的请求
每个筛选器返回 null(如果未找到该类型的授权),或自定义 AbstractAuthenticationToken
如果筛选器返回一个令牌,则将调用每个身份验证提供程序的支持(类)方法,如果该令牌应尝试身份验证,则该令牌将返回 true|false
然后,将在支持令牌的身份验证提供程序上调用尝试身份验证。在这里,您可以执行任何服务调用以对用户进行身份验证。然后,您可以抛出 LoginException 或调用 authentication.setAuthenticated(true),并返回令牌以成功进行身份验证。
我一直在使用此设置一段时间,支持各种身份验证方法(签名请求,用户名/密码,oauth等),并且效果很好。
您还可以将身份验证成功处理程序和身份验证Failuers处理程序传递到自定义安全筛选器,以提供自定义重定向策略和故障处理。
此外,请务必在过滤器的构造函数中设置蚂蚁匹配器,以控制过滤器也应用的 url 模式。例如,ldap 请求过滤器可能需要与任何请求“/*”进行检查,而用户名/密码过滤器只需在 POST 的 /login 或类似内容上进行检查即可。
示例代码:
1) 为要支持的每种身份验证类型创建自定义身份验证令牌
public class LDAPAuthorizationToken extends AbstractAuthenticationToken {
private String token;
public LDAPAuthorizationToken( String token ) {
super( null );
this.token = token;
}
public Object getCredentials() {
return token;
}
public Object getPrincipal() {
return null;
}
}
public class OTPAuthorizationToken extends UsernamePasswordAuthenticationToken {
private String otp;
public OTPAuthorizationToken( String username, String password, String otp ) {
super( username, password );
this.otp = otp;
}
public String getOTP() {
return otp;
}
}
2) 为每种类型的自定义安全筛选器
public class LDAPAuthorizationFilter extends AbstractAuthenticationProcessingFilter {
@Autowired
private UserDetailsService userDetailsService;
public LDAPAuthorizationFilter() {
super( "/*" ); // allow any request to contain an authorization header
}
public Authentication attemptAuthentication( HttpServletRequest request, HttpServletResponse response ) throws AuthenticationException
{
if ( request.getHeader( "Authorization" ) == null ) {
return null; // no header found, continue on to other security filters
}
// return a new authentication token to be processed by the authentication provider
return new LDAPAuthorizationToken( request.getHeader( "Authorization" ) );
}
}
public class OTPAuthorizationFilter extends AbstractAuthenticationProcessingFilter {
@Autowired
private UserDetailsService userDetailsService;
public OTPAuthorizationFilter() {
super( "/otp_login" );
}
public Authentication attemptAuthentication( HttpServletRequest request, HttpServletResponse response ) throws AuthenticationException
{
if ( request.getParameter( "username" ) == null || request.getParameter( "password" ) == null || request.getParameter( "otp" ) == null ) {
return null;
}
// return a new authentication token to be processed by the authentication provider
return new OTPAuthorizationToken( request.getParameter( "username" ), request.getParameter( "password" ), request.getParameter( "otp" ) );
}
}
3) 创建自定义身份验证提供程序
public class LDAPAuthenticationProvider implements AuthenticationProvider {
@Autowired
private MyAuthenticationService sampleService;
@Override
public Authentication authenticate( Authentication authentication ) throws AuthenticationException {
LDAPAuthorizationToken auth = (LDAPAuthorizationToken)authentication;
String username = sampleService.verifyToken( auth.getCredentials() );
if ( username == null ) {
throw new LoginException( "Invalid Token" );
}
auth.setAuthenticated( true );
return auth;
}
@Override
public boolean supports( Class<?> authentication ) {
if ( authentication.isAssignableFrom( LDAPAuthorizationToken.class ) ) {
return true;
}
return false;
}
}
public class OTPAuthenticationProvider implements AuthenticationProvider {
@Autowired
private MyAuthenticationService sampleService;
@Override
public Authentication authenticate( Authentication authentication ) throws AuthenticationException {
OTPAuthorizationToken auth = (OTPAuthorizationToken)authentication;
String error = sampleService.loginWithOTP( auth.getPrincipal(), auth.getCredentials(), auth.getOTP() );
if ( error != null ) {
throw new LoginException( error );
}
auth.setAuthenticated( true );
return auth;
}
@Override
public boolean supports( Class<?> authentication ) {
if ( authentication.isAssignableFrom( OTPAuthorizationToken.class ) ) {
return true;
}
return false;
}
}
4) 配置弹簧安全
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure( HttpSecurity http ) throws Exception {
// configure filters
http.addFilterBefore( new LDAPAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class );
http.addFilterBefore( new OTPAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class );
// configure authentication providers
http.authenticationProvider( new LDAPAuthenticationProvider() );
http.authenticationProvider( new OTPAuthenticationProvider() );
// disable csrf
http.csrf().disable();
// setup security
http.authorizeRequests()
.anyRequest()
.fullyAuthenticated()
.and().httpBasic();
}
}
希望有所帮助!