使用 Spring Security 4 以编程方式对用户进行身份验证
Posted
技术标签:
【中文标题】使用 Spring Security 4 以编程方式对用户进行身份验证【英文标题】:Programatically authenticate user with Spring Security 4 【发布时间】:2016-05-11 09:37:12 【问题描述】:我使用 inMemoryAuthentication 并且需要在访问特定端点时以编程方式对用户进行身份验证(出于测试原因)。因此我使用以下基于Programmatically login in a user using spring security的方法:
private void login(Role role)
logger.warn("Login User with role: " + role.toString());
Authentication auth =
new UsernamePasswordAuthenticationToken("user", "password", getAuthorities(role));
SecurityContext securityContext = SecurityContextHolder.getContext();
securityContext.setAuthentication(auth);
private Collection<GrantedAuthority> getAuthorities(Role role)
Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();
GrantedAuthority grantedAuthority = (GrantedAuthority) () -> role.toString();
grantedAuthorities.add(grantedAuthority);
return grantedAuthorities;
securityContext 设置正确(getAuthentication 按预期返回用户),但是,JSESSIONID cookie 未设置。
【问题讨论】:
【参考方案1】:我可以解决我的问题,但这并不容易,我不确定是否有更好的解决方案。
我创建了一个过滤器、一个自定义 authenticationProvider 和一个自定义 authenticationToken
public class E2EAuthenticationFilter extends GenericFilterBean
private final Logger logger = LoggerFactory.getLogger(E2EAuthenticationFilter.class);
private AuthenticationManager authenticationManager;
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException
Role role = null;
String username = null;
String password = null;
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
if(isLoginRequest(request.getRequestURI()))
String roleName = getRoleName(request.getRequestURI());
switch(roleName.toUpperCase())
case "ADMIN":
role = Role.ADMIN;
username = "admin";
password = "admin";
break;
case "REPORTER":
role = Role.REPORTER;
username = "reporter";
password = "reporter";
break;
default:
break;
authenticateUser(username, password, role);
chain.doFilter(request, response);
public AuthenticationManager getAuthenticationManager()
return authenticationManager;
public void setAuthenticationManager(AuthenticationManager authenticationManager)
this.authenticationManager = authenticationManager;
private Collection<GrantedAuthority> getAuthorities(Role role)
Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();
GrantedAuthority grantedAuthority = (GrantedAuthority) () -> "ROLE_"+role.toString();
grantedAuthorities.add(grantedAuthority);
return grantedAuthorities;
private String getRoleName(String uri)
String[] requestUriParts = uri.split("/");
return requestUriParts[requestUriParts.length-1];
private void authenticateUser(String username, String password, Role role)
E2EAuthenticationToken token = new E2EAuthenticationToken(username, password, getAuthorities(role));
Authentication authResult = authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authResult);
private boolean isLoginRequest(String uri)
return uri.matches("\\/e2e\\/auth\\/login\\/(\\w)+");
authProvider 类:
@Component
public class E2EAuthenticationProvider implements AuthenticationProvider
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException
E2EAuthenticationToken token = (E2EAuthenticationToken) authentication;
E2EAuthenticationToken authenticated = new E2EAuthenticationToken(token.getUsername(), token.getPassword(), token.getAuthorities());
authenticated.setAuthenticated(true);
return authenticated;
@Override
public boolean supports(Class<?> authentication)
return authentication.equals(E2EAuthenticationToken.class);
令牌类:
public class E2EAuthenticationToken extends AbstractAuthenticationToken
private String username;
private String password;
public E2EAuthenticationToken(String username, String password, Collection<? extends GrantedAuthority> authorities)
super(authorities);
this.username = username;
@Override
public Object getCredentials()
return this.username;
@Override
public Object getPrincipal()
return this.username;
public String getUsername()
return username;
public void setUsername(String username)
this.username = username;
public String getPassword()
return password;
public void setPassword(String password)
this.password = password;
最后是spring配置:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class InMemorySecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
private E2EAuthenticationProvider e2eAuthenticationProvider;
@Bean
public E2EAuthenticationFilter e2eAuthenticationFilter() throws Exception
E2EAuthenticationFilter filter = new E2EAuthenticationFilter();
filter.setAuthenticationManager( authenticationManager() );
return filter;
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception
auth.authenticationProvider(e2eAuthenticationProvider);
auth.inMemoryAuthentication()
.withUser("admin")
.password("admin")
.roles(Role.ADMIN.name())
.and()
.withUser("reporter")
.password("reporter")
.roles(Role.REPORTER.name());
@Override
protected void configure(HttpSecurity http) throws Exception
http
.requestMatchers().antMatchers("/api/**", "/e2e/auth/**", "/acuator/**")
.and().addFilterBefore(e2eAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.authorizeRequests()
.antMatchers("/actuator/health").permitAll()
.antMatchers("/actuator/info").permitAll()
.anyRequest().authenticated()
.and().httpBasic()
.and().csrf().disable();
您可能已经注意到,我将此代码用于端点(当然,它仅在 E2E 配置中可用)以登录用户进行 selenium 测试。
【讨论】:
以上是关于使用 Spring Security 4 以编程方式对用户进行身份验证的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Spring Security 3.1 以编程方式登录用户
如何以编程方式检查某个 URL 是不是需要使用 Spring Security 进行身份验证?
如何使用 DaoAuthenticationProvider 以编程方式使用 Spring Security 对用户进行身份验证