如何配置 spring security 以设置记住我服务,同时使用扩展 AbstractPreAuthenticatedProcessingFilter
的 customAuthenticationFilter 和自定义身份验证管理器。
我做了一个没有过滤器的例子,它工作得很好。然后,当我添加过滤器时, Spring 安全性停止使用“记住我”服务。
这是我的 spring 安全配置:
@Configuration
@EnableWebSecurity
public class SecurityContext extends WebSecurityConfigurerAdapter {
private static final Logger LOGGER = LoggerFactory.getLogger(SecurityContext.class);
@Autowired
private CustomUserDetailsService customUserDetailsService;
@Autowired
private CCUTokenService ccuTokenService;
@Autowired
private PersistanceTokenDaoImpl persistanceTokenDao;
@Autowired
private AutoLoginFilter autoLoginFilter;
/**
* Spring Security ignores request to static resources such as CSS or JS files. Theses requests
* will not be intercepted in AutoLoginFilter
*/
@Override
public void configure(WebSecurity web) throws Exception {
// Spring Security ignores request to static resources such as CSS or JS files.
// theses requests will not be intercepted in AutoLoginFilter
web.ignoring()
.antMatchers("/acceptCookies")
.antMatchers("/assets/**")
.antMatchers("/v2/api-docs") //swagger-ui
.antMatchers("/webjars/**")
.antMatchers("/wro/**")
.antMatchers("**/frag/**")
.antMatchers("**/fragment/**")
.antMatchers("**/script/beginner/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
RequestMatcher matcher = new RequestHeaderRequestMatcher("X-Requested-With");
LOGGER.debug("Creating Security Context ...");
http.rememberMe().rememberMeServices(rememberMeServices()).key("posc").and();
http.
sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().
csrf().requireCsrfProtectionMatcher(createCSRFMathers()).and();
//Add autologin filter
http.addFilter(autoLoginFilter)
.addFilterBefore(new TransactionIdRequestFilter(), AutoLoginFilter.class)
.exceptionHandling().defaultAuthenticationEntryPointFor(new Http401TimeoutEntryPoint(), matcher)
.and();
//Add form login
http.formLogin()
.successHandler(savedRequestAwareAuthenticationSuccessHandler())
.loginPage("/page/login")
.loginProcessingUrl("/page/login/authenticate")
.failureUrl("/page/login?loginError=true")
.and();
// Configures the logout function
http.logout()
.deleteCookies("JSESSIONID")
.logoutUrl("/logout")
.logoutSuccessUrl("/page/login?loginError=false")
.and();
// Configures url based authorization
// Anyone can access the following urls
http.authorizeRequests()
.antMatchers("posc://**",
"/connectedUser/mobileInfos",
"/dashboard/config/**",
"/page/checklogintoken/**",
"/page/httpError",
"/page/login/**",
"/page/manifest",
"/page/token/**",
"/service-scripting/**",
"/script/**")
.permitAll()
.antMatchers("/**")
.hasRole("USER");
}
private RequestMatcher createCSRFMathers() {
return new RequestMatcher() {
private Pattern allowedMethods = Pattern.compile("^GET$");
private AntPathRequestMatcher[] requestMatchers = {new AntPathRequestMatcher("/script/**"),
new AntPathRequestMatcher("/page/external/client/**"),
new AntPathRequestMatcher("/page/token")};
@Override
public boolean matches(HttpServletRequest request) {
if (allowedMethods.matcher(request.getMethod()).matches()) {
return false;
}
for (AntPathRequestMatcher rm : requestMatchers) {
if (rm.matches(request)) {
return false;
}
}
return true;
}
};
}
/**
* Configures the authentication manager bean which processes authentication requests.
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
}
/**
* This is used to hash the password of the user.
*/
@Bean
public ShaPasswordEncoder passwordEncoder() {
return new ShaPasswordEncoder(256);
}
@Bean
public AbstractRememberMeServices rememberMeServices() {
PersistentTokenBasedRememberMeServices rememberMeServices =
new PersistentTokenBasedRememberMeServices("posc",customUserDetailsService,persistentTokenRepository());
rememberMeServices.setAlwaysRemember(true);
rememberMeServices.setCookieName("remember-me-posc");
rememberMeServices.setTokenValiditySeconds(1209600);
return rememberMeServices;
}
@Bean
public PersistentTokenRepository persistentTokenRepository() {
CassandraTokenRepository db = new CassandraTokenRepository(persistanceTokenDao);
return db;
}
@Bean
public SavedRequestAwareAuthenticationSuccessHandler savedRequestAwareAuthenticationSuccessHandler() {
SavedRequestAwareAuthenticationSuccessHandler auth = new SavedRequestAwareAuthenticationSuccessHandler();
auth.setTargetUrlParameter("targetUrl");
return auth;
}
}
这是我的自定义身份验证管理器:
@Configuration
public class CustomAuthenticationManager implements AuthenticationManager {
protected static Logger logger = LoggerFactory.getLogger(CustomAuthenticationManager.class);
@Autowired
private BaseCoeurService baseCoeurService;
public CustomAuthenticationManager() {
}
public Authentication authenticate(Authentication auth) throws AuthenticationException {
logger.debug("Performing custom authentication");
try {
baseCoeurService.getUserByUsername(auth.getName());
} catch (ResourceNotFoundException e) {
throw new BadCredentialsException("User '" + auth.getName() + "' does not exists on BC !");
} catch(RestException e) {
throw new BadCredentialsException("Impossible to retrieve User " + auth.getName() + " from BC, cause : " + e.getMessage());
}
logger.debug("User details are good and ready to go");
return new UsernamePasswordAuthenticationToken(auth.getName(), auth.getCredentials(), getAuthorities(1));
}
/**
* Retrieves the correct ROLE type depending on the access level, where access level is an
* Integer. Basically, this interprets the access value whether it's for a regular user or admin.
*
* @param access an integer value representing the access of the user
* @return collection of granted authorities
*/
public Collection<GrantedAuthority> getAuthorities(Integer access) {
// Create a list of grants for this user
List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>(2);
// All users are granted with ROLE_USER access
// Therefore this user gets a ROLE_USER by default
logger.debug("Grant ROLE_USER to this user");
authList.add(new SimpleGrantedAuthority("ROLE_USER"));
// Check if this user has admin access
// We interpret Integer(1) as an admin user
if (access.compareTo(1) == 0) {
// User has admin access
logger.debug("Grant ROLE_ADMIN to this user");
authList.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
// Return list of granted authorities
return authList;
}
最佳答案
我通过添加 RememberMeAuthenticationFilter 解决了这个问题,其中我注入(inject)了自定义身份验证管理器和 RememberMe 服务,然后我将 Spring Security 配置为在 AbstractPreAuthenticatedProcessingFilter 之前使用此过滤器
http.addFilter(autoLoginFilter).addFilterBefore(new RememberMeAuthenticationFilter(autoLoginFilter.getAuthenticationManager(), rememberMeServices()),AutoLoginFilter.class)
.addFilterBefore(new TransactionIdRequestFilter(), AutoLoginFilter.class)
.exceptionHandling().defaultAuthenticationEntryPointFor(new Http401TimeoutEntryPoint(), matcher)
.and();
关于java - Spring 安全: Set Remember me Service while using AbstractPreAuthenticatedProcessingFilter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32067830/