spring cloud oauth2 替换用户信息

spring cloud oauth2 替换用户信息

在spring cloud 的oauth2认证中,有一个用户认证服务auth,提供客户端的认证,由于oauth2有多种授权方式,不同的授权采用的方式就不一样了。

在实际业务中,比如有个应用A,有自己的数据库A,需要auth授权后才能登陆,PC端登录的时候采用的是授权码模式,使用 @EnableOAuth2Sso 注解标记一个 WebSecurityConfigurerAdapter 类。当登录认证成功后会广播一个event事件,这个事件可以监听到,所以我们采用的是监听InteractiveAuthenticationSuccessEvent事件,这个是通过自动交互的手段来登录成功,比如cookie自动登录。具体实现细节如下,实际应用采用的是注释掉的代码,两种都可以参考:

   @EventListener
    public void authSuccessListener(InteractiveAuthenticationSuccessEvent event){
        System.out.println("哎呦喂,登录成功了");
        Authentication authentication=SecurityContextHolder.getContext().getAuthentication();
        //通用替换,针对用户名密码登录的
        if(authentication instanceof UsernamePasswordAuthenticationToken){
            UsernamePasswordAuthenticationToken originToken= (UsernamePasswordAuthenticationToken) authentication;
            String username= originToken.getName();
            System.out.println(username);
            //查找用户,这里直接模拟查到了用户,根据需求进行替换
            Person person=new Person(username,20);
            UsernamePasswordAuthenticationToken token=new UsernamePasswordAuthenticationToken(originToken.getPrincipal(),"N/A",originToken.getAuthorities());
            token.setDetails(person);
            SecurityContextHolder.getContext().setAuthentication(token);
        }
        //auth2替换
        //替换oauth认证的信息里的details,这里就不展示了
       /* if (authentication instanceof OAuth2Authentication) {
            OAuth2Authentication originalOAuth2Authentication = (OAuth2Authentication) authentication;
            if (!originalOAuth2Authentication.isClientOnly()) {
                Authentication userAuthentication = originalOAuth2Authentication.getUserAuthentication();
                if (userAuthentication instanceof UsernamePasswordAuthenticationToken) {
                    UsernamePasswordAuthenticationToken originalUsernamePasswordAuthentication = (UsernamePasswordAuthenticationToken) userAuthentication;

                    String username = (String) originalUsernamePasswordAuthentication.getPrincipal();
                    //可以根据username查找用户,这里模拟获取用户
                    Person person=new Person("二狗子",18);
                    if (person != null) {
                        //替换用户信息,权限信息根据自己的需求替换,这里直接取原来的
                        UsernamePasswordAuthenticationToken usernamePasswordAuthentication = new UsernamePasswordAuthenticationToken(originalUsernamePasswordAuthentication.getPrincipal(), "N/A", originalUsernamePasswordAuthentication.getAuthorities());
                        usernamePasswordAuthentication.setDetails(person);

                        OAuth2Authentication oauth2Authentication = new OAuth2Authentication(originalOAuth2Authentication.getOAuth2Request(), usernamePasswordAuthentication);
                        oauth2Authentication.setDetails(originalOAuth2Authentication.getDetails());

                        SecurityContextHolder.getContext().setAuthentication(oauth2Authentication);
                    }
                }
            }
        }*/
    }

 

但是在APP登录的时候采用的授权方式是密码,这样认证的时候是根据认证token,只是一个token没有像pc端那样有cookie去自动验证,服务器是通过资源服务器认证的,只要token通过就可以访问被资源服务器保护的资源,这里都是/api/的接口。这种情况下就不能监听登录事件了,要在每次验证通过后去替换oauthAuthentication里面的details了,这样接口获取本应用当前登录用户的时候就可以直接获取了。那么如何实现认证成功后替换呢,根据spring security的尿性,增加一个filter,在最后一个filter之前替换。(注意:自定义过滤器交给spring托管可能出现doFilter被执行两次的问题,可以加个标记解决)

 

@Component
public class CustomerSecurityFilter extends GenericFilterBean {
    //加个标记,防止被执行两次
    //在spring容器托管的GenericFilterBean的bean,都会自动加入到servlet的filter chain,而我们还额外把filter加入到了spring security的
    //最后一个Filter之前。而spring security也是一系列的filter,在mvc的filter之前执行。因此在鉴权通过的情况下,就会先后各执行一次。
    private static final String FILTER_APPLIED = "__spring_security_customerFilter_filterApplied";
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        if(servletRequest.getAttribute(FILTER_APPLIED)!=null){
           filterChain.doFilter(servletRequest,servletResponse);
           return;
        }
     
        System.out.println("哎呦呵,来啦");
        //替换用户信息,具体替换步骤参考上一个替换,这个用户最好存入缓存,毕竟过滤器过滤的请求挺多,每次都要查询很坑的
        servletRequest.setAttribute(FILTER_APPLIED,true);
        filterChain.doFilter(servletRequest,servletResponse);
    }
}
 @Autowired
    private CustomerSecurityFilter customerSecurityFilter;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/","/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/chat")
                .permitAll()
                .and()
                .logout()
                .permitAll()
                .and()
                .addFilterBefore(customerSecurityFilter,SwitchUserFilter.class);
    }

 

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/100307.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 深入解析 kubernetes 资源管理,容器云牛人有话说

    深入解析 kubernetes 资源管理,容器云牛人有话说

    2022年4月3日
    42
  • 好的留言本,看看呀!

    好的留言本,看看呀!

    2021年7月23日
    47
  • spring cloud微服务架构设计

    spring cloud微服务架构设计1 概述分别从整体层级 开发视图 部署视图三个角度 对整个系统的微服务架构进行 解剖 整体层级关注调用的层级 从终端人机界面到物联网 开发视图则主要面向开发人员 描述了系统工程结构 模块及关联关系 部署视图则是系统最终部署时的拓扑图 通过这些视角可以较为清晰的明白整个微服务架构设计思路 2 整体层级视图自顶向下的一张调用层次关系图 详细的说明 见下方的开发视图和部署视

    2025年9月19日
    5
  • windows服务器审计日志存放位置,windows服务器审计日志存放位置[通俗易懂]

    windows服务器审计日志存放位置,windows服务器审计日志存放位置[通俗易懂]windows服务器审计日志存放位置内容精选换一换Manager的审计日志默认保存在数据库中,如果长期保留可能引起数据目录的磁盘空间不足问题,管理员如果需要将审计日志保存到其他归档服务器,可以在FusionInsightManager设置转储参数及时自动转储,便于管理审计日志信息。若用户未配置审计日志转储,当审计日志达到十万条,系统自动将这十万条审计日志保存到文件中。保存路径为主管理节为加强对…

    2022年6月4日
    178
  • 黑苹果MacOS Big Sur 11.0 安装教程及驱动工具

    黑苹果MacOS Big Sur 11.0 安装教程及驱动工具最新黑苹果MacOSBigSur11.0安装教程,附带各电脑EFI驱动合集、原版引导镜像,图文并茂简单易懂…一、准备工作1.一个8G以上的U盘(安装10.15Catalina必须要16G及以上的U盘);2.MacOS镜像、TransMac(刻录工具)、DiskGenius(分区工具)、EasyUEFI(引导工区)、EFI驱动文件。安装工具获取链接:https://pan.baidu.com/s/1pwUVVo1Ud4yxO29k_ckTBw提取码:qs05安装镜像

    2022年6月3日
    160
  • 移动端开发规范

    移动端开发规范移动端开发规范引言:最近得空,整理一些平时工作中要求的开发规范,浅薄之处还请大家多指教。目录移动端开发规范代码规范基本原则代码清晰一致性通用规范类命名方法命名变量命名常量命名枚举类型命名图片命名通用规范通用设计规范开屏页版本号版本检查开屏页广告推送通用测试用例及处理规范规范用例数据埋点规范…

    2022年6月24日
    33

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号