- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用 jHipster 生成的 webapp 实现记住我的功能。我正在更新一个旧的项目登录页面,其中会有一个记住我的复选框。
我遇到的问题是我正在实现的 RememberMeServices 不起作用。准确的说,没有调用onLoginSuccess方法,也没有进行持久化token的初始化。
然而,CustomPersistentRememberMeServices 的注销方法被调用。
我有一个自定义记住我的服务,定义如下:
@Service("rememberMeServices")
public class CustomPersistentRememberMeServices extends
AbstractRememberMeServices {
private final Logger log = LoggerFactory.getLogger(CustomPersistentRememberMeServices.class);
// Token is valid for one month
private static final int TOKEN_VALIDITY_DAYS = 31;
private static final int TOKEN_VALIDITY_SECONDS = 60 * 60 * 24 * TOKEN_VALIDITY_DAYS;
private static final int DEFAULT_SERIES_LENGTH = 16;
private static final int DEFAULT_TOKEN_LENGTH = 16;
private SecureRandom random;
@Inject
private PersistentTokenRepository persistentTokenRepository;
@Inject
private UserRepository userRepository;
@Inject
public CustomPersistentRememberMeServices(Environment env, org.springframework.security.core.userdetails
.UserDetailsService userDetailsService) {
super(env.getProperty("jhipster.security.rememberme.key"), userDetailsService);
random = new SecureRandom();
}
@Override
@Transactional
protected UserDetails processAutoLoginCookie(String[] cookieTokens, HttpServletRequest request,
HttpServletResponse response) {
PersistentToken token = getPersistentToken(cookieTokens);
String login = token.getUser().getLogin();
// Token also matches, so login is valid. Update the token value, keeping the *same* series number.
log.debug("Refreshing persistent login token for user '{}', series '{}'", login, token.getSeries());
token.setTokenDate(LocalDate.now());
token.setTokenValue(generateTokenData());
token.setIpAddress(request.getRemoteAddr());
token.setUserAgent(request.getHeader("User-Agent"));
try {
persistentTokenRepository.saveAndFlush(token);
addCookie(token, request, response);
} catch (DataAccessException e) {
log.error("Failed to update token: ", e);
throw new RememberMeAuthenticationException("Autologin failed due to data access problem", e);
}
return getUserDetailsService().loadUserByUsername(login);
}
@Override
protected void onLoginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication
successfulAuthentication) {
String login = successfulAuthentication.getName();
log.debug("Creating new persistent login for user {}", login);
PersistentToken token = userRepository.findOneByLogin(login).map(u -> {
PersistentToken t = new PersistentToken();
t.setSeries(generateSeriesData());
t.setUser(u);
t.setTokenValue(generateTokenData());
t.setTokenDate(LocalDate.now());
t.setIpAddress(request.getRemoteAddr());
t.setUserAgent(request.getHeader("User-Agent"));
return t;
}).orElseThrow(() -> new UsernameNotFoundException("User " + login + " was not found in the database"));
try {
persistentTokenRepository.saveAndFlush(token);
addCookie(token, request, response);
} catch (DataAccessException e) {
log.error("Failed to save persistent token ", e);
}
}
/**
* When logout occurs, only invalidate the current token, and not all user sessions.
* <p/>
* The standard Spring Security implementations are too basic: they invalidate all tokens for the
* current user, so when he logs out from one browser, all his other sessions are destroyed.
*/
@Override
@Transactional
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
String rememberMeCookie = extractRememberMeCookie(request);
if (rememberMeCookie != null && rememberMeCookie.length() != 0) {
try {
String[] cookieTokens = decodeCookie(rememberMeCookie);
PersistentToken token = getPersistentToken(cookieTokens);
persistentTokenRepository.delete(token);
} catch (InvalidCookieException ice) {
log.info("Invalid cookie, no persistent token could be deleted");
} catch (RememberMeAuthenticationException rmae) {
log.debug("No persistent token found, so no token could be deleted");
}
}
super.logout(request, response, authentication);
}
/**
* Validate the token and return it.
*/
private PersistentToken getPersistentToken(String[] cookieTokens) {
if (cookieTokens.length != 2) {
throw new InvalidCookieException("Cookie token did not contain " + 2 +
" tokens, but contained '" + Arrays.asList(cookieTokens) + "'");
}
String presentedSeries = cookieTokens[0];
String presentedToken = cookieTokens[1];
PersistentToken token = persistentTokenRepository.findOne(presentedSeries);
if (token == null) {
// No series match, so we can't authenticate using this cookie
throw new RememberMeAuthenticationException("No persistent token found for series id: " + presentedSeries);
}
// We have a match for this user/series combination
log.info("presentedToken={} / tokenValue={}", presentedToken, token.getTokenValue());
if (!presentedToken.equals(token.getTokenValue())) {
// Token doesn't match series value. Delete this session and throw an exception.
persistentTokenRepository.delete(token);
throw new CookieTheftException("Invalid remember-me token (Series/token) mismatch. Implies previous " +
"cookie theft attack.");
}
if (token.getTokenDate().plusDays(TOKEN_VALIDITY_DAYS).isBefore(LocalDate.now())) {
persistentTokenRepository.delete(token);
throw new RememberMeAuthenticationException("Remember-me login has expired");
}
return token;
}
private String generateSeriesData() {
byte[] newSeries = new byte[DEFAULT_SERIES_LENGTH];
random.nextBytes(newSeries);
return new String(Base64.encode(newSeries));
}
private String generateTokenData() {
byte[] newToken = new byte[DEFAULT_TOKEN_LENGTH];
random.nextBytes(newToken);
return new String(Base64.encode(newToken));
}
private void addCookie(PersistentToken token, HttpServletRequest request, HttpServletResponse response) {
setCookie(
new String[]{token.getSeries(), token.getTokenValue()},
TOKEN_VALIDITY_SECONDS, request, response);
}
并且这样定义了一个安全配置类:
@Configuration
public class OAuth2ServerConfiguration {
@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Inject
private Http401UnauthorizedEntryPoint authenticationEntryPoint;
@Inject
private AjaxLogoutSuccessHandler ajaxLogoutSuccessHandler;
@Inject
private RememberMeServices rememberMeServices;
@Inject
private Environment env;
@Override
public void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.rememberMe()
.rememberMeServices(rememberMeServices)
.rememberMeParameter("remember-me")
.key(env.getProperty("jhipster.security.rememberme.key"))
.and()
.logout()
.logoutUrl("/api/logout")
.logoutSuccessHandler(ajaxLogoutSuccessHandler)
.deleteCookies("JSESSIONID", "CSRF-TOKEN")
.and()
.csrf()
.disable()
.headers()
.frameOptions().disable()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.requestMatchers()
.antMatchers("/oauth/token")
.and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers("/api/authenticate").permitAll()
.antMatchers("/api/register").permitAll()
.antMatchers("/api/logs/**").hasAnyAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/api/**").authenticated()
.antMatchers("/metrics/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/health/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/trace/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/dump/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/shutdown/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/beans/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/configprops/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/info/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/autoconfig/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/env/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/trace/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/liquibase/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/api-docs/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/protected/**").authenticated();
}
}
@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Inject
private DataSource dataSource;
@Inject
private JHipsterProperties jHipsterProperties;
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
@Inject
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints
.tokenStore(tokenStore())
.authenticationManager(authenticationManager);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.allowFormAuthenticationForClients();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient(jHipsterProperties.getSecurity().getAuthentication().getOauth().getClientid())
.scopes("read", "write")
.authorities(AuthoritiesConstants.ADMIN, AuthoritiesConstants.USER)
.authorizedGrantTypes("password", "refresh_token", "authorization_code", "implicit")
.secret(jHipsterProperties.getSecurity().getAuthentication().getOauth().getSecret())
.accessTokenValiditySeconds(jHipsterProperties.getSecurity().getAuthentication().getOauth().getTokenValidityInSeconds());
}
}
谢谢。
最佳答案
在 spring security oauth 中,由于 RememberMeAuthenticationFilter 未关联到登录 url (/oauth/token),记住我服务无法工作,即使在使用 rememberMe 配置器之后也是如此。
为了能够具有记住我的功能,必须使用刷新 token 来不断更新访问 token ,然后才能被记住。
您可以阅读这两篇文章以了解如何做到这一点。 http://www.baeldung.com/rest-api-spring-oauth2-angularjs http://www.baeldung.com/spring-security-oauth2-remember-me
关于java - Spring Security - 记住我自定义服务 onLoginSuccess 未使用 oauth2 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46084050/
我观察到很少有逆向工程师,他们将十进制转换为十六进制的速度如此之快。这简直太神奇了。我一直没有机会问他们。就我个人而言,我真的很讨厌这个转换,而且我总是使用计算器进行转换。 我想知道这种转换是否有某种
我有一个程序使用三个 JTextField 字段作为主要数据输入字段。我想要它,以便当用户终止程序然后再次打开它时,他们的最后一个条目仍将在字段中。 我怎样才能做到这一点?我需要某种数据库还是有更简单
我有以下脚本将 jquery 生成的对象的颜色更改为蓝色: $(".objects_list").live('click', function(event) { $(this).css("co
这个问题在这里已经有了答案: Is it a good idea to memoize all of my react components? (2 个答案) 关闭去年。 我知道使用 React.m
我在 R 中编写了一个递归函数并使用 memoise 来加速它。我试图通过在 Rcpp 中编写它然后记住 Rcpp 函数来进一步加快它的速度,但 R 函数更快。为什么会这样,有什么方法可以加快我的使用
我的应用程序包含几个 View ,我想在应用程序启动且用户尚未完成向导时显示一个小设置。我知道我可以使用 NSUserDefaults 实现此目的,但我不确定如何使其根据 NSUserDefaults
我正在从一台机器(相同版本的Delphi)开发应用程序。该应用程序的原始版本使用了TMS包中的TMoneyEdit组件。在移动项目时,我想删除对该产品的依赖。因此,在源代码中,我删除了TMoneyEd
我有一个触发器,希望将相同的随机值插入两个表中。我该怎么做呢? 在TableAB上插入后创建触发器insertTrigger 开始 插入TableA(id,num)VALUES(RANDOM(),1)
我有以下代码,通过 .swf 解决方案将服务器 IP 复制到客户端的剪贴板。正如您所看到的,它用成功的“已复制”消息替换了“复制 IP”按钮。我该如何让“复制 IP”按钮在显示成功消息 5 秒后返回,
我正在使用 GPS 定位功能,问题是权限弹出窗口一遍又一遍地出现(每次新的网址刷新/按 F5 键)。 我如何记住用户在浏览器中选择的状态(已批准或已拒绝)。 if (navigator.geoloca
有一个按钮(实际上有很多),它有一个事件处理程序: el.onclick = function(){ if(this.className.indexOf("minimized") != -1)
我正在制作一个纯 html+JavaScript 幻灯片。幻灯片位于网站的侧边栏中,该网站为每个具有幻灯片侧边栏的页面加载了 php。唯一没有侧边栏的页面是主页。 幻灯片放映工作正常。然而,可以理解的
我想制作一个 Chrome 扩展程序,它将存储来自用户的潜在大型代码片段(以及代码片段的名称)并使用它们。 我希望用户能够上传包含这些片段的文件(或者更好的是,将这些片段复制并粘贴到扩展程序选项页面的
我有一个方法是 pure function并需要一段时间才能运行。我想记住这个方法,以便后续调用更快。我可以在 Groovy 的文档中看到,您可以通过以下方式内存闭包: foo = {…}.memoi
[jQuery][1] 始终记住您的鼠标触发器,无论是单击还是悬停。因此,如果您鼠标输入和鼠标退出四次,它将执行该事件四次。 如何让它“忘记”触发器,以便当我用鼠标输入和退出触发器时它只执行一次? 编
对于我的开发人员工作,我几乎整天都在 *nix shell 环境中工作,但似乎仍然无法记住我每天不使用的程序的名称和参数细节。我想知道其他“临时健忘症患者”是如何处理这个问题的。你有一个大的备忘单吗?
我有一个表格,在客户填写各种表格后,我希望能够浏览网站,并返回表格并保持填写状态。 我考虑过在浏览器的客户端中保留 cookie,您可能会推荐其他方法吗? 关于代码,这里是 o 想到的 javascr
好的,我已经实现了 Facebook 登录按钮: loginButton.readPermissions = ["public_profile", "email", "user_friends"] l
我在移动应用程序中使用 AngularJS。用户能够将产品添加到订单中。但是我使用了不同的选项卡,以便用户可以在类别之间切换,并且对于每个类别,都会显示属于该类别的产品。这些产品可以添加到他/她的订单
我有一个使用自定义适配器、布局和模型类的 ListView (包含文本和复选框)。我想将选定的复选框保存在 sqlite 数据库中,以便当我导航到另一个 Activity 然后返回时,选定的复选框保持
我是一名优秀的程序员,十分优秀!