覆盖现有的 Spring Security 身份验证
Posted
技术标签:
【中文标题】覆盖现有的 Spring Security 身份验证【英文标题】:Override the existing Spring Security authentication 【发布时间】:2017-07-17 20:04:18 【问题描述】:如何通过调用 Web 服务来,当它失败时,需要重定向一些第三方登录页面。
为了调用这个认证网络服务,我需要获取一些 ServletRequest 参数,为了重定向,我需要访问 ServletResponse。
因此我需要找出一些带有 ServletRequest 和 ServletResponse 参数的身份验证方法。
但是,我还是没有找到这样的 ProcessingFilter 或 AuthenticationProvider。
根据 Spring Security basic 看来我必须重写 AuthenticationProvider 相关的身份验证方法。
根据用例,我必须实现Spring Security Pre-authentication,
但问题是 PreAuthenticatedAuthenticationProvider 相关的“authenticate”方法只有 Authentication 参数。
PreAuthenticatedAuthenticationProvider
public class PreAuthenticatedAuthenticationProvider implements
AuthenticationProvider, InitializingBean, Ordered
public Authentication authenticate(Authentication authentication)
作为解决方案,是否有可能使用AuthenticationFailureHandler 的自定义实现?
谢谢。
【问题讨论】:
【参考方案1】:我已经通过以下方式解决了这个问题,
实现自定义 AbstractPreAuthenticatedProcessingFilter重写 doFilter 方法
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
try
// Get current Authentication object from SecurityContext
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
// Call for third party WS when the Authenticator object is null
if (auth == null)
logger.debug("doFilter : Proceed the authentication");
String appId = "My_APP_ID";
String redirectURL = request.getRequestURL().toString();
// Call for third party WS for get authenticate
if (WS_Authenticator.isAuthenticated(appId, redirectURL))
// Successfully authenticated
logger.debug("doFilter : WS authentication success");
// Get authenticated username
String userName = WS_Authenticator.getUserName();
// Put that username to request
request.setAttribute("userName", userName);
else
String redirectURL = WS_Authenticator.getAuthorizedURL();
logger.debug("doFilter : WS authentication failed");
logger.debug("doFilter : WS redirect URL : " + redirectURL);
((HttpServletResponse) response).setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
((HttpServletResponse) response).sendRedirect(redirectURL);
// Return for bypass the filter chain
return;
else
logger.debug("doFilter : Already authenticated");
catch (Exception e)
logger.error("doFilter: " + e.getMessage());
super.doFilter(request, response, chain);
return;
重写 getPreAuthenticatedCredentials 方法
@Override
protected Object getPreAuthenticatedCredentials(HttpServletRequest request)
// Get authenticated username
String[] credentials = new String[1];
credentials[0] = (String) request.getAttribute("userName");
return credentials;
实现 CustomAuthenticationUserDetailsServiceImpl
覆盖 loadUserDetails 方法
public class CustomAuthenticationUserDetailsServiceImpl implements AuthenticationUserDetailsService<Authentication>
protected static final Logger logger = Logger.getLogger(CustomAuthenticationUserDetailsServiceImpl.class);
@Autowired
private UserDataService userDataService;
public UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException
// Get authenticated username
String[] credentials = (String[]) token.getCredentials();
String userName = credentials[0];
try
// Get user by username
User user = userDataService.getDetailsByUserName(userName);
// Get authorities username
List<String> roles = userDataService.getRolesByUserName(userName);
user.setCustomerAuthorities(roles);
return user;
catch (Exception e)
logger.debug("loadUserDetails: User not found! " + e.getMessage());
return null;
【讨论】:
以上是关于覆盖现有的 Spring Security 身份验证的主要内容,如果未能解决你的问题,请参考以下文章
使用 Spring Security 在一个应用程序中结合数据库和 SAML 身份验证
如何将 Spring Security 与我现有的 REST Web 服务集成
使用身份验证回退配置 Crowd Spring Security