//具体的验证令牌方法
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException
{
DemoToken token = (DemoToken) authentication;
//从数据源map中获取用户密码
String rawPass = map.get(token.getUserName());
//验证密码,如果不相等,就抛出异常
if (!token.getPassword().equals(rawPass))
{
token.setAuthenticated(false);
throw new BadCredentialsException(“认证有误:令牌校验失败” );
}
//验证成功
token.setAuthenticated(true);
return token;
}
/**
*判断令牌是否被支持
*@param authentication 这里仅仅DemoToken令牌被支持
*@return
*/
@Override
public boolean supports(Class<?> authentication)
{
return authentication.isAssignableFrom(DemoToken.class);
}
}
DemoAuthProvider模拟了一个简单的数据源并且加载了两个用户。在其authenticate验证方法中,将入参DemoToken令牌中的用户名和密码与模拟数据源中的用户信息进行匹配,若匹配成功,则验证成功。
演示程序的第三步:定制一个过滤器类,从请求中获取用户信息并组装成定制凭证/令牌,交给认证管理者。在生产场景中,认证信息一般为某个HTTP头部信息(如Cookie信息、Token信息等)。本演示程序中的过滤器类为DemoAuthFilter,从请求头中获取token字段,解析之后组装成DemoToken令牌实例,提交给AuthenticationManager进行验证。DemoAuthFilter的代码如下:
public class DemoAuthFilter extends OncePerRequestFilter
{
//认证失败的处理器
private AuthenticationFailureHandler failureHandler = new AuthFailureHandler();
…
//authenticationManager是认证流程的入口,接收一个Authentication令牌对象作为参数 private AuthenticationManager authenticationManager;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException
{
…
AuthenticationException failed = null;
try
{
Authentication returnToken=null;
boolean succeed=false;
//从请求头中获取认证信息
String token = request.getHeader
(SessionConstants.AUTHORIZATION_HEAD);
String[] parts = token.split(“,” );
//组装令牌
DemoToken demoToken = new DemoToken(parts[0],parts[1]);
//提交给AuthenticationManager进行令牌验证
returnToken = (DemoToken) this.getAuthenticationManager()
.authenticate(demoToken);
//获取认证成功标志
succeed=demoToken.isAuthenticated();
if (succeed)
{
//认证成功,设置上下文令牌
SecurityContextHolder.getContext().setAuthentication
(returnToken);
//执行后续的操作
filterChain.doFilter(request, response);
return;
}
} catch (Exception e)
{
logger.error(“认证有误”, e);
failed = new AuthenticationServiceException(“请求头认证消息格式错误”,e );
}
if(failed == null)
{
failed = new AuthenticationServiceException(“认证失败”);
}
//认证失败了
SecurityContextHolder.clearContext();
failureHandler.onAuthenticationFailure(request, response, failed);
}
…
}
为了使得过滤器能够生效,必须将过滤