使用 Java Config 的 Spring Security 自定义身份验证过滤器
Posted
技术标签:
【中文标题】使用 Java Config 的 Spring Security 自定义身份验证过滤器【英文标题】:Spring Security custom authentication filter using Java Config 【发布时间】:2015-02-14 22:55:04 【问题描述】:我正在尝试在基本 Web 应用程序中使用 Java 配置配置 Spring Security,以使用 URL 请求参数中提供的加密令牌对外部 Web 服务进行身份验证。
我希望(我认为)有一个安全过滤器来拦截来自登录门户的请求(它们都转到 /authenticate),过滤器将使用 AuthenticationProvider 来处理身份验证过程的业务逻辑。
Login Portal --> Redirect '\authenticate' (+ Token) --> Authenticate Token back to Login Portal (WS) --> 如果成功获取角色和设置用户。
我已经创建了一个过滤器..
@Component
public final class OEWebTokenFilter extends GenericFilterBean
@Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException
if (request instanceof HttpServletRequest)
OEToken token = extractToken(request);
// dump token into security context (for authentication-provider to pick up)
SecurityContextHolder.getContext().setAuthentication(token);
chain.doFilter(request, response);
一个身份验证提供者...
@Component
public final class OEWebTokenAuthenticationProvider implements AuthenticationProvider
@Autowired
private WebTokenService webTokenService;
@Override
public boolean supports(final Class<?> authentication)
return OEWebToken.class.isAssignableFrom(authentication);
@Override
public Authentication authenticate(final Authentication authentication)
if (!(authentication instanceof OEWebToken))
throw new AuthenticationServiceException("expecting a OEWebToken, got " + authentication);
try
// validate token locally
OEWebToken token = (OEWebToken) authentication;
checkAccessToken(token);
// validate token remotely
webTokenService.validateToken(token);
// obtain user info from the token
User userFromToken = webTokenService.obtainUserInfo(token);
// obtain the user from the db
User userFromDB = userDao.findByUserName(userFromToken.getUsername());
// validate the user status
checkUserStatus(userFromDB);
// update ncss db with values from OE
updateUserInDb(userFromToken, userFromDB);
// determine access rights
List<GrantedAuthority> roles = determineRoles(userFromDB);
// put account into security context (for controllers to use)
return new AuthenticatedAccount(userFromDB, roles);
catch (AuthenticationException e)
throw e;
catch (Exception e)
// stop non-AuthenticationExceptions. otherwise full stacktraces returned to the requester
throw new AuthenticationServiceException("Internal error occurred");
还有我的 Spring 安全配置
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
OESettings oeSettings;
@Bean(name="oeAuthenticationService")
public AuthenticationService oeAuthenticationService() throws AuthenticationServiceException
return new AuthenticationServiceImpl(new OEAuthenticationServiceImpl(), oeSettings.getAuthenticateUrl(), oeSettings.getApplicationKey());
@Autowired
private OEWebTokenFilter tokenFilter;
@Autowired
private OEWebTokenAuthenticationProvider tokenAuthenticationProvider;
@Autowired
private OEWebTokenEntryPoint tokenEntryPoint;
@Bean(name="authenticationManager")
@Override
public AuthenticationManager authenticationManagerBean() throws Exception
return super.authenticationManagerBean();
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception
auth.authenticationProvider(tokenAuthenticationProvider);
@Bean
public FilterRegistrationBean filterRegistrationBean ()
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(tokenFilter);
registrationBean.setEnabled(false);
return registrationBean;
@Override
protected void configure(HttpSecurity http) throws Exception
http.csrf().disable()
.authorizeRequests()
.antMatchers("/authenticate**").permitAll()
.antMatchers("/resources/**").hasAuthority("ROLE_USER")
.antMatchers("/home**").hasAuthority("ROLE_USER")
.antMatchers("/personSearch**").hasAuthority("ROLE_ADMIN")
// Spring Boot actuator endpoints
.antMatchers("/autoconfig**").hasAuthority("ROLE_ADMIN")
.antMatchers("/beans**").hasAuthority("ROLE_ADMIN")
.antMatchers("/configprops**").hasAuthority("ROLE_ADMIN")
.antMatchers("/dump**").hasAuthority("ROLE_ADMIN")
.antMatchers("/env**").hasAuthority("ROLE_ADMIN")
.antMatchers("/health**").hasAuthority("ROLE_ADMIN")
.antMatchers("/info**").hasAuthority("ROLE_ADMIN")
.antMatchers("/mappings**").hasAuthority("ROLE_ADMIN")
.antMatchers("/metrics**").hasAuthority("ROLE_ADMIN")
.antMatchers("/trace**").hasAuthority("ROLE_ADMIN")
.and()
.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class)
.authenticationProvider(tokenAuthenticationProvider)
.antMatcher("/authenticate/**")
.exceptionHandling().authenticationEntryPoint(tokenEntryPoint)
.and()
.logout().logoutSuccessUrl(oeSettings.getUrl());
我的问题是我的 SpringConfig 类中过滤器的配置。我希望过滤器仅在请求 /authenticate URL 时生效,我已将 .antMatcher("/authenticate/**") 添加到过滤器配置中。
.and()
.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class)
.authenticationProvider(tokenAuthenticationProvider)
.antMatcher("/authenticate/**")
.exceptionHandling().authenticationEntryPoint(tokenEntryPoint)
当我在所有其他 URL 中的该行不再受保护时,我可以手动导航到 /home 而不进行身份验证,删除该行并 /home 进行身份验证。
我应该声明一个仅适用于特定 URL 的过滤器吗?
如何在保持其他 URL 安全的同时实现这一点?
【问题讨论】:
【参考方案1】:我已通过在调用身份验证提供程序之前检查过滤器中的身份验证状态解决了我的问题....
配置
.and()
.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class)
.authenticationProvider(tokenAuthenticationProvider)
.exceptionHandling().authenticationEntryPoint(tokenEntryPoint)
过滤器
@Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
throws IOException, ServletException
logger.debug(this + "received authentication request from " + request.getRemoteHost() + " to " + request.getLocalName());
if (request instanceof HttpServletRequest)
if (isAuthenticationRequired())
// extract token from header
OEWebToken token = extractToken(request);
// dump token into security context (for authentication-provider to pick up)
SecurityContextHolder.getContext().setAuthentication(token);
else
logger.debug("session already contained valid Authentication - not checking again");
chain.doFilter(request, response);
private boolean isAuthenticationRequired()
// apparently filters have to check this themselves. So make sure they have a proper AuthenticatedAccount in their session.
Authentication existingAuth = SecurityContextHolder.getContext().getAuthentication();
if ((existingAuth == null) || !existingAuth.isAuthenticated())
return true;
if (!(existingAuth instanceof AuthenticatedAccount))
return true;
// current session already authenticated
return false;
【讨论】:
你能贴出这些类的代码吗:OEWebToken
、AuthenticatedAccount
和extractToken(request)
方法实现?我会为我的休息服务提供很多帮助。提前致谢。
我无法完成这项工作。 this baeldung blog post帮我解决了类似的情况以上是关于使用 Java Config 的 Spring Security 自定义身份验证过滤器的主要内容,如果未能解决你的问题,请参考以下文章
Spring Cloud Config - Git 存储库错误
spring-batch (java-config) 使用 JobExecutionDecider 识别和执行步骤
Spring Security sec:使用 Java Config 授权标签
无法通过 spring.cloud.config.enabled:false 禁用 Spring Cloud Config