当前位置: 首页 > 知识库问答 >
问题:

Spring Oauth2 - 重新加载主体

卢阳成
2023-03-14

我已经用Spring Security模块实现了OAuth2密码授权。我添加了自己的UserDetails和UserDetailsService (jdbc)实现。我将用户注入到我控制器中:

@AuthenticationPrincipal User user

其中User是我的UserDetails实现。现在我想添加在不刷新令牌的情况下更改用户数据的可能性。

我尝试更新校长:

User updatedUser = ...
Authentication newAuth = new UsernamePasswordAuthenticationToken(updatedUser, updatedUser.getPassword(), updatedUser.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(newAuth);

但它不起作用,当我调用另一个控制器方法时,它会返回旧的User对象。

有没有办法在不刷新令牌的情况下更改用户数据?是否有任何解决方案可以使Spring Security性始终从数据库(而不是从缓存)加载用户数据?

共有2个答案

柳墨一
2023-03-14

我不确定,但这只是一个猜测,我想你也需要清除SecurityContext

首先,使用<code>SecurityContextHolder清除安全上下文。clearContext() 然后您的代码设置身份验证

Authentication newAuth = new UsernamePasswordAuthenticationToken(updatedUser, updatedUser.getPassword(), updatedUser.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(newAuth);
林龙野
2023-03-14

我从这个答案中找到了一种方法来实现这一点。我创建了HttpSessionSecurityContextRepository

@Bean
public ReloadUserPerRequestHttpSessionSecurityContextRepository userDetailContextRepository() {
    return new ReloadUserPerRequestHttpSessionSecurityContextRepository();
}

并将其添加到我的HttpSecurity,从WebSecurityConfigurerAdapter类中,如下所示:

    .and()
        .csrf()
            .csrfTokenRepository(csrfTokenRepository())
    .and()
        .securityContext()
            .securityContextRepository(userDetailContextRepository())

下面是在每次请求时获取更新用户信息的示例代码。您可以从API服务器或oauth2配置用户信息url获取。

public class ReloadUserPerRequestHttpSessionSecurityContextRepository extends HttpSessionSecurityContextRepository {

    @Override
    public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) {
        SecurityContext context = super.loadContext(requestResponseHolder);

        Authentication auth = context.getAuthentication();
        if (auth != null && auth instanceof OAuth2Authentication) {
            OAuth2Authentication oldAuth = (OAuth2Authentication) auth;
            if (oldAuth.getPrincipal() instanceof LinkedHashMap) {
                createNewUserDetailsFromPrincipal(oldAuth.getPrincipal());
            }
            context.setAuthentication(oldAuth);
        }
        return context;
    }

    @SuppressWarnings("unchecked")
    private void createNewUserDetailsFromPrincipal(Object principal) {
        LinkedHashMap<String, Object> userDetailInfo = (LinkedHashMap<String, Object>) principal;
        // fetch User informations from your API server or your database or
        // 'user-info-url' of oauth2 endpoint
        userDetailInfo.put("name", "EDITED_USER_NAME");
    }

}
 类似资料:
  • 问题内容: 这是一个非常基本的问题-但我无法通过在线搜索找到答案。 我正在使用python控制ArcGIS,并且有一个简单的python脚本,该脚本调用了一些预先编写的代码。 但是,当我对预写代码进行更改时,它似乎没有导致任何更改。我导入了此模块,并尝试刷新它,但是没有任何反应。 我什至将它调用的文件移到了另一个位置,脚本仍然可以正常工作。昨天我做的一件事是我将所有python文件都添加到sys路

  • 我试图在Angular应用程序中调用我的登录服务,但我遇到了CORS错误。我已经在WebSecurity配置适配器上添加了cors配置。我已经尝试了下面的一些配置。邮递员一切都很好。 授权服务器配置RADAPTER 资源服务器配置RADAPTER Web安全配置r适配器

  • 问题内容: 我有一个带有php include的Div Tag,该div用来填充该信息,我想要做的是使它每隔15秒调用一次,以便它可以在那里更新信息,而不必重新加载整个网页。我试图用JavaScript / jQuery做到这一点,但似乎无法正常工作 这是我在搜索一些内容后所拥有的,然后发生的是,它加载了Small.php,但不会每15秒刷新一次或更新信息。 请帮忙! 我应该添加所有应显示的php

  • 问题内容: 我只是很好奇,因为我已经在FragmentActivity中设置了Fragment选项卡,如何从FragmentActivity或Fragment本身重新加载片段,以清除并重新加载该选项卡。我本质上需要重新选择选项卡以替换片段时发生的相同事情。有一种简单的方法可以执行此操作并重新加载片段吗? 问题答案: 创建一个方法,该方法开始FragmentTransaction,分离片段,然后提交

  • 当用户从用户界面更改配置时,我想动态地重新加载log4j附加器(RollingFileAppender)。 我已经通过编程删除了追加器,并用新的配置值创建了新的追加器。在此之后,appender broked MaxBackupIndex和MaxFileSize无法正常工作。但是如果我更改了文件名(日志文件名),那么它可以正常工作。 能帮我解决这个问题吗?

  • 我在我的应用程序中使用导航栏,每次我选择一个项目时,它都会加载一个片段。 我能够使用相同的文本字段和按钮保存片段的状态,但有一个片段可以加载地图、添加标记、集群并执行。 每次我转到另一个菜单项并返回时,它都会重新加载所有内容,例如AsyncTask、Cluster、Markers。我如何停止此片段以不再重新创建地图并在返回时保存状态: Udate 1:我更新了代码,但问题仍然存在 主要活动: 主片