You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@dubbo.apache.org by "houkunlin (via GitHub)" <gi...@apache.org> on 2023/04/11 15:03:55 UTC

[GitHub] [dubbo] houkunlin opened a new issue, #12073: 与 SpringSecurity 合并使用时,使用自定义的 UserDetails 对象,用户登录成功后无法发起请求

houkunlin opened a new issue, #12073:
URL: https://github.com/apache/dubbo/issues/12073

   <!-- If you need to report a security issue please visit https://github.com/apache/dubbo/security/policy -->
   
   - [ ] I have searched the [issues](https://github.com/apache/dubbo/issues) of this repository and believe that this is not a duplicate.
   
   ### Environment
   
   * Dubbo version: 3.2.0-beta.6   /  org.apache.dubbo:dubbo-bom:3.2.0-beta.6
   * Java version: java 17
   * springboot 3.0.5
   * org.springframework.cloud:spring-cloud-dependencies:2022.0.1
   * com.alibaba.cloud:spring-cloud-alibaba-dependencies:2022.0.0.0-RC1
   * com.alibaba.fastjson2:fastjson2:2.0.27
   
   ### Steps to reproduce this issue
   
   1. Dubbo请求获取用户信息
   2. 返回自定义的UserDetails对象,登录成功
   3. Dubbo再次请求获取用户信息
   4. 控制台报错
   
   自定义一个 UserDetails 对象,在SpringBootSecurity登录成功后返回自定义的 UserDetails 对象,此时再次发起Dubbo请求,无法获取数据,控制台报错。
   
   ```
   2023-04-11T22:54:15.413+08:00  WARN 64592 --- [o-auto-1-exec-3] o.a.d.r.c.s.wrapper.MockClusterInvoker   :  [DUBBO] fail-mock: getLocalIdentifier fail-mock enabled , url : consumer://172.29.237.2/com.houkunlin.cloud.micro.rpc.UserDubboService?application=api-auth-server&background=false&check=true&dubbo=2.0.2&executor-management-mode=default&file-cache=false&interface=com.houkunlin.cloud.micro.rpc.UserDubboService&methods=getAssignAuthorities,getLeaderIds,getLocalIdentifier,getUserAllPermissionValues,getUserByUserId,getUserByUsername,loginFailureAction,loginSuccessAction,saveUserLog,updatePassword&mock=true&pid=64592&qos.enable=true&qos.port=9622&register-mode=instance&register.ip=172.29.237.2&release=3.2.0-beta.6&revision=0.0.7-SNAPSHOT-plain&side=consumer&sticky=false&timestamp=1681224224385&unloadClusterRelated=false, dubbo version: 3.2.0-beta.6, current host: 172.29.237.2, error code: 2-17. This may be caused by failed to mock invoke, go to https://dubbo.apache.org/faq/2/17 to
  find instructions. 
   
   org.apache.dubbo.rpc.RpcException: Failed to invoke the method getLocalIdentifier in the service com.houkunlin.cloud.micro.rpc.UserDubboService. Tried 3 times of the providers [172.29.237.2:20883] (1/1) from the registry 192.168.0.5:8848 on the consumer 172.29.237.2 using the dubbo version 3.2.0-beta.6. Last error is: Failed to invoke remote method: getLocalIdentifier, provider: DefaultServiceInstance{serviceName='system-user-server', host='172.29.237.2', port=20883, enabled=true, healthy=true, metadata={dubbo.metadata-service.url-params={"prefer.serialization":"fastjson2,hessian2","version":"1.0.0","dubbo":"2.0.2","release":"3.2.0-beta.6","side":"provider","port":"20883","protocol":"dubbo"}, dubbo.endpoints=[{"port":20883,"protocol":"dubbo"}], dubbo.metadata.revision=998f69ef376ecb6920e7f05d9e6f0b14, dubbo.metadata.storage-type=local, timestamp=1681209402712}}, service{name='com.houkunlin.cloud.micro.rpc.UserDubboService',group='null',version='null',protocol='dubbo',port='20883',
 params={executor-management-mode=default, side=provider, file-cache=false, release=3.2.0-beta.6, methods=getAssignAuthorities,getLeaderIds,getLocalIdentifier,getUserAllPermissionValues,getUserByUserId,getUserByUsername,loginFailureAction,loginSuccessAction,saveUserLog,updatePassword, deprecated=false, dubbo=2.0.2, interface=com.houkunlin.cloud.micro.rpc.UserDubboService, service-name-mapping=true, register-mode=instance, generic=false, revision=0.0.7-SNAPSHOT-plain, application=system-user-server, prefer.serialization=fastjson2,hessian2, background=false, dynamic=true, anyhost=true},}, cause: org.apache.dubbo.remoting.RemotingException: java.lang.RuntimeException: objectMapper! deserialize error java.lang.IllegalArgumentException: The class with com.houkunlin.cloud.micro.login.LoginUserDetails and name of com.houkunlin.cloud.micro.login.LoginUserDetails is not in the allowlist. If you believe this class is safe to deserialize, please provide an explicit mapping using Jackson annotat
 ions or by providing a Mixin. If the serialization is only done by a trusted source, you can also enable default typing. See https://github.com/spring-projects/spring-security/issues/4370 for details
   java.lang.RuntimeException: objectMapper! deserialize error java.lang.IllegalArgumentException: The class with com.houkunlin.cloud.micro.login.LoginUserDetails and name of com.houkunlin.cloud.micro.login.LoginUserDetails is not in the allowlist. If you believe this class is safe to deserialize, please provide an explicit mapping using Jackson annotations or by providing a Mixin. If the serialization is only done by a trusted source, you can also enable default typing. See https://github.com/spring-projects/spring-security/issues/4370 for details
   	at org.apache.dubbo.spring.security.jackson.ObjectMapperCodec.deserialize(ObjectMapperCodec.java:50)
   	at org.apache.dubbo.spring.security.jackson.ObjectMapperCodec.deserialize(ObjectMapperCodec.java:58)
   	at org.apache.dubbo.spring.security.filter.ContextHolderAuthenticationResolverFilter.getSecurityContext(ContextHolderAuthenticationResolverFilter.java:56)
   	at org.apache.dubbo.spring.security.filter.ContextHolderAuthenticationResolverFilter.invoke(ContextHolderAuthenticationResolverFilter.java:45)
   	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   	at org.apache.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.java:192)
   	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   	at org.apache.dubbo.rpc.filter.ClassLoaderFilter.invoke(ClassLoaderFilter.java:54)
   	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   	at org.apache.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.java:41)
   	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   	at org.apache.dubbo.rpc.filter.ProfilerServerFilter.invoke(ProfilerServerFilter.java:64)
   	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   	at org.apache.dubbo.rpc.filter.ContextFilter.invoke(ContextFilter.java:144)
   	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CallbackRegistrationInvoker.invoke(FilterChainBuilder.java:194)
   	at org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol$1.reply(DubboProtocol.java:159)
   	at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.java:103)
   	at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:186)
   	at org.apache.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:53)
   	at org.apache.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:62)
   	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
   	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
   	at org.apache.dubbo.common.threadlocal.InternalRunnable.run(InternalRunnable.java:41)
   	at java.base/java.lang.Thread.run(Thread.java:833)
   ```
   
   尝试使用 `ObjectMapperCodecCustomer` 来处理 ObjectMapperCodec.ObjectMapper ,增加`context.setMixInAnnotations(LoginUserDetails.class, LoginUserDetailsMixin.class);`,断点发现配置正常生效,在Dubbo请求之前断点能够看到生效的信息,但是依旧无法完成反序列化,并且控制台报错的位置在调试模式无法断点。
   
   复制 `CoreJackson2Module` 类到本地进行覆盖,取消 `// context.setMixInAnnotations(User.class, UserMixin.class);`配置,使用官方的 User 对象,调试运行发现本地 `CoreJackson2Module` 正常执行,并且ObjectMapperCodec.ObjectMapper无UserMixin配置,此时依旧能够请求成功,但是我想要的并不是使用官方的User对象,而是想要自定义的UserDetails对象。
   
   上面两种方式,一种是增加自己的 Mixin 对象,一种是取消官方的 Mixin 对象配置,两种方式均无法正常生效,虽然断点看到的配置是生效的,但是实际Dubbo请求时执行的配置与断点的配置不一致
   
   
   Pls. provide [GitHub address] to reproduce this issue.
   
   ### Expected Behavior
   
   <!-- What do you expect from the above steps?-->
   
   ### Actual Behavior
   
   <!-- What actually happens? -->
   
   If there is an exception, please attach the exception trace:
   
   ```
   Just put your stack trace here!
   ```
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org


[GitHub] [dubbo] jojocodeX commented on issue #12073: 与 SpringSecurity 合并使用时,使用自定义的 UserDetails 对象,用户登录成功后无法发起请求

Posted by "jojocodeX (via GitHub)" <gi...@apache.org>.
jojocodeX commented on issue #12073:
URL: https://github.com/apache/dubbo/issues/12073#issuecomment-1505308643

   > * [ ]  I have searched the [issues](https://github.com/apache/dubbo/issues) of this repository and believe that this is not a duplicate.
   > 
   > ### Environment
   > * Dubbo version: 3.2.0-beta.6   /  org.apache.dubbo:dubbo-bom:3.2.0-beta.6
   > * Java version: java 17
   > * springboot 3.0.5
   > * org.springframework.cloud:spring-cloud-dependencies:2022.0.1
   > * com.alibaba.cloud:spring-cloud-alibaba-dependencies:2022.0.0.0-RC1
   > * com.alibaba.fastjson2:fastjson2:2.0.27
   > 
   > ### Steps to reproduce this issue
   > 1. Dubbo请求获取用户信息
   > 2. 返回自定义的UserDetails对象,登录成功
   > 3. Dubbo再次请求获取用户信息
   > 4. 控制台报错
   > 
   > 自定义一个 UserDetails 对象,在SpringBootSecurity登录成功后返回自定义的 UserDetails 对象,此时再次发起Dubbo请求,无法获取数据,控制台报错。
   > 
   > ```
   > 2023-04-11T22:54:15.413+08:00  WARN 64592 --- [o-auto-1-exec-3] o.a.d.r.c.s.wrapper.MockClusterInvoker   :  [DUBBO] fail-mock: getLocalIdentifier fail-mock enabled , url : consumer://172.29.237.2/com.houkunlin.cloud.micro.rpc.UserDubboService?application=api-auth-server&background=false&check=true&dubbo=2.0.2&executor-management-mode=default&file-cache=false&interface=com.houkunlin.cloud.micro.rpc.UserDubboService&methods=getAssignAuthorities,getLeaderIds,getLocalIdentifier,getUserAllPermissionValues,getUserByUserId,getUserByUsername,loginFailureAction,loginSuccessAction,saveUserLog,updatePassword&mock=true&pid=64592&qos.enable=true&qos.port=9622&register-mode=instance&register.ip=172.29.237.2&release=3.2.0-beta.6&revision=0.0.7-SNAPSHOT-plain&side=consumer&sticky=false&timestamp=1681224224385&unloadClusterRelated=false, dubbo version: 3.2.0-beta.6, current host: 172.29.237.2, error code: 2-17. This may be caused by failed to mock invoke, go to https://dubbo.apache.org/faq/2/17 
 to find instructions. 
   > 
   > org.apache.dubbo.rpc.RpcException: Failed to invoke the method getLocalIdentifier in the service com.houkunlin.cloud.micro.rpc.UserDubboService. Tried 3 times of the providers [172.29.237.2:20883] (1/1) from the registry 192.168.0.5:8848 on the consumer 172.29.237.2 using the dubbo version 3.2.0-beta.6. Last error is: Failed to invoke remote method: getLocalIdentifier, provider: DefaultServiceInstance{serviceName='system-user-server', host='172.29.237.2', port=20883, enabled=true, healthy=true, metadata={dubbo.metadata-service.url-params={"prefer.serialization":"fastjson2,hessian2","version":"1.0.0","dubbo":"2.0.2","release":"3.2.0-beta.6","side":"provider","port":"20883","protocol":"dubbo"}, dubbo.endpoints=[{"port":20883,"protocol":"dubbo"}], dubbo.metadata.revision=998f69ef376ecb6920e7f05d9e6f0b14, dubbo.metadata.storage-type=local, timestamp=1681209402712}}, service{name='com.houkunlin.cloud.micro.rpc.UserDubboService',group='null',version='null',protocol='dubbo',port='20883
 ',params={executor-management-mode=default, side=provider, file-cache=false, release=3.2.0-beta.6, methods=getAssignAuthorities,getLeaderIds,getLocalIdentifier,getUserAllPermissionValues,getUserByUserId,getUserByUsername,loginFailureAction,loginSuccessAction,saveUserLog,updatePassword, deprecated=false, dubbo=2.0.2, interface=com.houkunlin.cloud.micro.rpc.UserDubboService, service-name-mapping=true, register-mode=instance, generic=false, revision=0.0.7-SNAPSHOT-plain, application=system-user-server, prefer.serialization=fastjson2,hessian2, background=false, dynamic=true, anyhost=true},}, cause: org.apache.dubbo.remoting.RemotingException: java.lang.RuntimeException: objectMapper! deserialize error java.lang.IllegalArgumentException: The class with com.houkunlin.cloud.micro.login.LoginUserDetails and name of com.houkunlin.cloud.micro.login.LoginUserDetails is not in the allowlist. If you believe this class is safe to deserialize, please provide an explicit mapping using Jackson annot
 ations or by providing a Mixin. If the serialization is only done by a trusted source, you can also enable default typing. See https://github.com/spring-projects/spring-security/issues/4370 for details
   > java.lang.RuntimeException: objectMapper! deserialize error java.lang.IllegalArgumentException: The class with com.houkunlin.cloud.micro.login.LoginUserDetails and name of com.houkunlin.cloud.micro.login.LoginUserDetails is not in the allowlist. If you believe this class is safe to deserialize, please provide an explicit mapping using Jackson annotations or by providing a Mixin. If the serialization is only done by a trusted source, you can also enable default typing. See https://github.com/spring-projects/spring-security/issues/4370 for details
   > 	at org.apache.dubbo.spring.security.jackson.ObjectMapperCodec.deserialize(ObjectMapperCodec.java:50)
   > 	at org.apache.dubbo.spring.security.jackson.ObjectMapperCodec.deserialize(ObjectMapperCodec.java:58)
   > 	at org.apache.dubbo.spring.security.filter.ContextHolderAuthenticationResolverFilter.getSecurityContext(ContextHolderAuthenticationResolverFilter.java:56)
   > 	at org.apache.dubbo.spring.security.filter.ContextHolderAuthenticationResolverFilter.invoke(ContextHolderAuthenticationResolverFilter.java:45)
   > 	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   > 	at org.apache.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.java:192)
   > 	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   > 	at org.apache.dubbo.rpc.filter.ClassLoaderFilter.invoke(ClassLoaderFilter.java:54)
   > 	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   > 	at org.apache.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.java:41)
   > 	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   > 	at org.apache.dubbo.rpc.filter.ProfilerServerFilter.invoke(ProfilerServerFilter.java:64)
   > 	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   > 	at org.apache.dubbo.rpc.filter.ContextFilter.invoke(ContextFilter.java:144)
   > 	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   > 	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CallbackRegistrationInvoker.invoke(FilterChainBuilder.java:194)
   > 	at org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol$1.reply(DubboProtocol.java:159)
   > 	at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.java:103)
   > 	at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:186)
   > 	at org.apache.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:53)
   > 	at org.apache.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:62)
   > 	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
   > 	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
   > 	at org.apache.dubbo.common.threadlocal.InternalRunnable.run(InternalRunnable.java:41)
   > 	at java.base/java.lang.Thread.run(Thread.java:833)
   > ```
   > 
   > 尝试使用 `ObjectMapperCodecCustomer` 来处理 ObjectMapperCodec.ObjectMapper ,增加`context.setMixInAnnotations(LoginUserDetails.class, LoginUserDetailsMixin.class);`,断点发现配置正常生效,在Dubbo请求之前断点能够看到生效的信息,但是依旧无法完成反序列化,并且控制台报错的位置在调试模式无法断点。
   > 
   > 复制 `CoreJackson2Module` 类到本地进行覆盖,取消 `// context.setMixInAnnotations(User.class, UserMixin.class);`配置,使用官方的 User 对象,调试运行发现本地 `CoreJackson2Module` 正常执行,并且ObjectMapperCodec.ObjectMapper无UserMixin配置,此时依旧能够请求成功,但是我想要的并不是使用官方的User对象,而是想要自定义的UserDetails对象。
   > 
   > 上面两种方式,一种是增加自己的 Mixin 对象,一种是取消官方的 Mixin 对象配置,两种方式均无法正常生效,虽然断点看到的配置是生效的,但是实际Dubbo请求时执行的配置与断点的配置不一致
   > 
   > Pls. provide [GitHub address] to reproduce this issue.
   > 
   > ### Expected Behavior
   > ### Actual Behavior
   > If there is an exception, please attach the exception trace:
   > 
   > ```
   > Just put your stack trace here!
   > ```
   ![8D4F4C39-9B2D-4ee5-9E77-0D7BDC8B19A1](https://user-images.githubusercontent.com/15051594/231476277-0dbbfb34-a376-4865-ab18-2843363cd021.png)
   
   ![2](https://user-images.githubusercontent.com/15051594/231476556-32fb3584-ff38-4de4-beac-4a2937b66e80.png)
   
   
   ![2](https://user-images.githubusercontent.com/15051594/231476853-6793edc0-fbd6-4e3e-ae3f-fe8064221f71.png)
   
   ![2](https://user-images.githubusercontent.com/15051594/231477137-7a82ee52-8657-441c-aecb-0aeccb9749c2.png)
   ![3](https://user-images.githubusercontent.com/15051594/231477384-89cd973a-6151-4641-ad9c-7f94670ae70b.png)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org


Re: [I] 与 SpringSecurity 合并使用时,使用自定义的 UserDetails 对象,用户登录成功后无法发起请求 [dubbo]

Posted by "CrazyHZM (via GitHub)" <gi...@apache.org>.
CrazyHZM closed issue #12073: 与 SpringSecurity 合并使用时,使用自定义的 UserDetails 对象,用户登录成功后无法发起请求
URL: https://github.com/apache/dubbo/issues/12073


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org


[GitHub] [dubbo] jojocodeX commented on issue #12073: 与 SpringSecurity 合并使用时,使用自定义的 UserDetails 对象,用户登录成功后无法发起请求

Posted by "jojocodeX (via GitHub)" <gi...@apache.org>.
jojocodeX commented on issue #12073:
URL: https://github.com/apache/dubbo/issues/12073#issuecomment-1505283591

   在本地进行了相应的自定义序列化器,没有复现该错误,麻烦你提供下相关的代码


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org


[GitHub] [dubbo] jojocodeX commented on issue #12073: 与 SpringSecurity 合并使用时,使用自定义的 UserDetails 对象,用户登录成功后无法发起请求

Posted by "jojocodeX (via GitHub)" <gi...@apache.org>.
jojocodeX commented on issue #12073:
URL: https://github.com/apache/dubbo/issues/12073#issuecomment-1505312131

   > > * [ ]   I have searched the [issues](https://github.com/apache/dubbo/issues) of this repository and believe that this is not a duplicate.
   > > 
   > > ### Environment
   > > 
   > > * Dubbo version: 3.2.0-beta.6   /  org.apache.dubbo:dubbo-bom:3.2.0-beta.6
   > > * Java version: java 17
   > > * springboot 3.0.5
   > > * org.springframework.cloud:spring-cloud-dependencies:2022.0.1
   > > * com.alibaba.cloud:spring-cloud-alibaba-dependencies:2022.0.0.0-RC1
   > > * com.alibaba.fastjson2:fastjson2:2.0.27
   > > 
   > > ### Steps to reproduce this issue
   > > 
   > > 1. Dubbo请求获取用户信息
   > > 2. 返回自定义的UserDetails对象,登录成功
   > > 3. Dubbo再次请求获取用户信息
   > > 4. 控制台报错
   > > 
   > > 自定义一个 UserDetails 对象,在SpringBootSecurity登录成功后返回自定义的 UserDetails 对象,此时再次发起Dubbo请求,无法获取数据,控制台报错。
   > > ```
   > > 2023-04-11T22:54:15.413+08:00  WARN 64592 --- [o-auto-1-exec-3] o.a.d.r.c.s.wrapper.MockClusterInvoker   :  [DUBBO] fail-mock: getLocalIdentifier fail-mock enabled , url : consumer://172.29.237.2/com.houkunlin.cloud.micro.rpc.UserDubboService?application=api-auth-server&background=false&check=true&dubbo=2.0.2&executor-management-mode=default&file-cache=false&interface=com.houkunlin.cloud.micro.rpc.UserDubboService&methods=getAssignAuthorities,getLeaderIds,getLocalIdentifier,getUserAllPermissionValues,getUserByUserId,getUserByUsername,loginFailureAction,loginSuccessAction,saveUserLog,updatePassword&mock=true&pid=64592&qos.enable=true&qos.port=9622&register-mode=instance&register.ip=172.29.237.2&release=3.2.0-beta.6&revision=0.0.7-SNAPSHOT-plain&side=consumer&sticky=false&timestamp=1681224224385&unloadClusterRelated=false, dubbo version: 3.2.0-beta.6, current host: 172.29.237.2, error code: 2-17. This may be caused by failed to mock invoke, go to https://dubbo.apache.org/faq/2/1
 7 to find instructions. 
   > > 
   > > org.apache.dubbo.rpc.RpcException: Failed to invoke the method getLocalIdentifier in the service com.houkunlin.cloud.micro.rpc.UserDubboService. Tried 3 times of the providers [172.29.237.2:20883] (1/1) from the registry 192.168.0.5:8848 on the consumer 172.29.237.2 using the dubbo version 3.2.0-beta.6. Last error is: Failed to invoke remote method: getLocalIdentifier, provider: DefaultServiceInstance{serviceName='system-user-server', host='172.29.237.2', port=20883, enabled=true, healthy=true, metadata={dubbo.metadata-service.url-params={"prefer.serialization":"fastjson2,hessian2","version":"1.0.0","dubbo":"2.0.2","release":"3.2.0-beta.6","side":"provider","port":"20883","protocol":"dubbo"}, dubbo.endpoints=[{"port":20883,"protocol":"dubbo"}], dubbo.metadata.revision=998f69ef376ecb6920e7f05d9e6f0b14, dubbo.metadata.storage-type=local, timestamp=1681209402712}}, service{name='com.houkunlin.cloud.micro.rpc.UserDubboService',group='null',version='null',protocol='dubbo',port='208
 83',params={executor-management-mode=default, side=provider, file-cache=false, release=3.2.0-beta.6, methods=getAssignAuthorities,getLeaderIds,getLocalIdentifier,getUserAllPermissionValues,getUserByUserId,getUserByUsername,loginFailureAction,loginSuccessAction,saveUserLog,updatePassword, deprecated=false, dubbo=2.0.2, interface=com.houkunlin.cloud.micro.rpc.UserDubboService, service-name-mapping=true, register-mode=instance, generic=false, revision=0.0.7-SNAPSHOT-plain, application=system-user-server, prefer.serialization=fastjson2,hessian2, background=false, dynamic=true, anyhost=true},}, cause: org.apache.dubbo.remoting.RemotingException: java.lang.RuntimeException: objectMapper! deserialize error java.lang.IllegalArgumentException: The class with com.houkunlin.cloud.micro.login.LoginUserDetails and name of com.houkunlin.cloud.micro.login.LoginUserDetails is not in the allowlist. If you believe this class is safe to deserialize, please provide an explicit mapping using Jackson ann
 otations or by providing a Mixin. If the serialization is only done by a trusted source, you can also enable default typing. See https://github.com/spring-projects/spring-security/issues/4370 for details
   > > java.lang.RuntimeException: objectMapper! deserialize error java.lang.IllegalArgumentException: The class with com.houkunlin.cloud.micro.login.LoginUserDetails and name of com.houkunlin.cloud.micro.login.LoginUserDetails is not in the allowlist. If you believe this class is safe to deserialize, please provide an explicit mapping using Jackson annotations or by providing a Mixin. If the serialization is only done by a trusted source, you can also enable default typing. See https://github.com/spring-projects/spring-security/issues/4370 for details
   > > 	at org.apache.dubbo.spring.security.jackson.ObjectMapperCodec.deserialize(ObjectMapperCodec.java:50)
   > > 	at org.apache.dubbo.spring.security.jackson.ObjectMapperCodec.deserialize(ObjectMapperCodec.java:58)
   > > 	at org.apache.dubbo.spring.security.filter.ContextHolderAuthenticationResolverFilter.getSecurityContext(ContextHolderAuthenticationResolverFilter.java:56)
   > > 	at org.apache.dubbo.spring.security.filter.ContextHolderAuthenticationResolverFilter.invoke(ContextHolderAuthenticationResolverFilter.java:45)
   > > 	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   > > 	at org.apache.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.java:192)
   > > 	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   > > 	at org.apache.dubbo.rpc.filter.ClassLoaderFilter.invoke(ClassLoaderFilter.java:54)
   > > 	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   > > 	at org.apache.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.java:41)
   > > 	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   > > 	at org.apache.dubbo.rpc.filter.ProfilerServerFilter.invoke(ProfilerServerFilter.java:64)
   > > 	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   > > 	at org.apache.dubbo.rpc.filter.ContextFilter.invoke(ContextFilter.java:144)
   > > 	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   > > 	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CallbackRegistrationInvoker.invoke(FilterChainBuilder.java:194)
   > > 	at org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol$1.reply(DubboProtocol.java:159)
   > > 	at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.java:103)
   > > 	at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:186)
   > > 	at org.apache.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:53)
   > > 	at org.apache.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:62)
   > > 	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
   > > 	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
   > > 	at org.apache.dubbo.common.threadlocal.InternalRunnable.run(InternalRunnable.java:41)
   > > 	at java.base/java.lang.Thread.run(Thread.java:833)
   > > ```
   > > 
   > > 
   > >     
   > >       
   > >     
   > > 
   > >       
   > >     
   > > 
   > >     
   > >   
   > > 尝试使用 `ObjectMapperCodecCustomer` 来处理 ObjectMapperCodec.ObjectMapper ,增加`context.setMixInAnnotations(LoginUserDetails.class, LoginUserDetailsMixin.class);`,断点发现配置正常生效,在Dubbo请求之前断点能够看到生效的信息,但是依旧无法完成反序列化,并且控制台报错的位置在调试模式无法断点。
   > > 复制 `CoreJackson2Module` 类到本地进行覆盖,取消 `// context.setMixInAnnotations(User.class, UserMixin.class);`配置,使用官方的 User 对象,调试运行发现本地 `CoreJackson2Module` 正常执行,并且ObjectMapperCodec.ObjectMapper无UserMixin配置,此时依旧能够请求成功,但是我想要的并不是使用官方的User对象,而是想要自定义的UserDetails对象。
   > > 上面两种方式,一种是增加自己的 Mixin 对象,一种是取消官方的 Mixin 对象配置,两种方式均无法正常生效,虽然断点看到的配置是生效的,但是实际Dubbo请求时执行的配置与断点的配置不一致
   > > Pls. provide [GitHub address] to reproduce this issue.
   > > ### Expected Behavior
   > > ### Actual Behavior
   > > If there is an exception, please attach the exception trace:
   > > ```
   > > Just put your stack trace here!
   > > ```
   > 
   > ![8D4F4C39-9B2D-4ee5-9E77-0D7BDC8B19A1](https://user-images.githubusercontent.com/15051594/231476277-0dbbfb34-a376-4865-ab18-2843363cd021.png)
   > 
   > ![2](https://user-images.githubusercontent.com/15051594/231476556-32fb3584-ff38-4de4-beac-4a2937b66e80.png)
   > 
   > ![2](https://user-images.githubusercontent.com/15051594/231476853-6793edc0-fbd6-4e3e-ae3f-fe8064221f71.png)
   > 
   > ![2](https://user-images.githubusercontent.com/15051594/231477137-7a82ee52-8657-441c-aecb-0aeccb9749c2.png) ![3](https://user-images.githubusercontent.com/15051594/231477384-89cd973a-6151-4641-ad9c-7f94670ae70b.png)
   > 
   > 在本地进行了相应的自定义序列化器,没有复现该错误,你可以提供下序列化器相关的代码
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org


[GitHub] [dubbo] jojocodeX commented on issue #12073: 与 SpringSecurity 合并使用时,使用自定义的 UserDetails 对象,用户登录成功后无法发起请求

Posted by "jojocodeX (via GitHub)" <gi...@apache.org>.
jojocodeX commented on issue #12073:
URL: https://github.com/apache/dubbo/issues/12073#issuecomment-1505419542

   > @jojocodeX 我这两天把我代码提取一下,尽量提供一个复现的完整代码出来。 目前与你贴出的代码有一点区别,我的 LoginUserDetails 是直接实现了接口,而不是继承 `public class LoginUserDetails implements UserDetails, CredentialsContainer`。下面先放一下我的几个类的代码,完整的简化复现版本,需要多花点时间来搞。
   > 
   > 1. SpringBootSecurity第一次请求 `org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername` 方法发起 Dubbo 调用时,能够正常返回信息,此时多次调用 Dubbo 获取数据都正常
   > 2. 当登录成功后,在 `org.springframework.security.web.authentication.AuthenticationSuccessHandler` 再次发起一次 Dubbo 调用就会报错
   > 
   > ```java
   > @JsonDeserialize(using = LoginUserDetailsDeserializer.class)
   > @Getter
   > @EqualsAndHashCode
   > @Accessors(fluent = true)
   > public class LoginUserDetails implements UserDetails, CredentialsContainer {
   > 
   >     private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
   >     /**
   >      * 机构ID
   >      */
   >     private final Long orgId;
   >     /**
   >      * 部门ID
   >      */
   >     private final Long deptId;
   >     /**
   >      * 用户ID
   >      */
   >     private final Long userId;
   >     /**
   >      * 用户名,实际存储的是用户ID
   >      */
   >     private final String username;
   >     /**
   >      * 权限代码列表
   >      */
   >     private final Set<GrantedAuthority> authorities;
   >     /**
   >      * 账号未过期
   >      */
   >     private final boolean accountNonExpired;
   >     /**
   >      * 账号未锁定
   >      */
   >     private final boolean accountNonLocked;
   >     /**
   >      * 密码未过期
   >      */
   >     private final boolean credentialsNonExpired;
   >     /**
   >      * 是否启用
   >      */
   >     private final boolean enabled;
   >     /**
   >      * 用户密码
   >      */
   >     private String password;
   > 
   >     public LoginUserDetails(final LoginUserVo user, final String credential, final Set<String> permissions) {
   >         this.username = ObjectUtils.getDisplayString(user.getId());
   >         this.password = credential;
   >         this.enabled = user.isEnabled();
   >         this.accountNonExpired = !user.isExpired();
   >         this.credentialsNonExpired = true;
   >         this.accountNonLocked = true;
   >         this.authorities = permissions.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toSet());
   >         this.orgId = user.getOrgId();
   >         this.deptId = user.getDeptId();
   >         this.userId = user.getId();
   >     }
   > 
   >     public LoginUserDetails(Long orgId, Long deptId, Long userId, String username, Set<GrantedAuthority> authorities,
   >                             boolean accountNonExpired, boolean accountNonLocked, boolean credentialsNonExpired,
   >                             boolean enabled, String password) {
   >         this.orgId = orgId;
   >         this.deptId = deptId;
   >         this.userId = userId;
   >         this.username = username;
   >         this.authorities = authorities;
   >         this.accountNonExpired = accountNonExpired;
   >         this.accountNonLocked = accountNonLocked;
   >         this.credentialsNonExpired = credentialsNonExpired;
   >         this.enabled = enabled;
   >         this.password = password;
   >     }
   > 
   >     @Override
   >     public void eraseCredentials() {
   >         this.password = null;
   >     }
   > 
   >     @Override
   >     public Collection<? extends GrantedAuthority> getAuthorities() {
   >         return authorities;
   >     }
   > 
   >     @Override
   >     public String getPassword() {
   >         return password;
   >     }
   > 
   >     @Override
   >     public String getUsername() {
   >         return username;
   >     }
   > 
   >     @Override
   >     public boolean isAccountNonExpired() {
   >         return accountNonExpired;
   >     }
   > 
   >     @Override
   >     public boolean isAccountNonLocked() {
   >         return accountNonLocked;
   >     }
   > 
   >     @Override
   >     public boolean isCredentialsNonExpired() {
   >         return credentialsNonExpired;
   >     }
   > 
   >     @Override
   >     public boolean isEnabled() {
   >         return enabled;
   >     }
   > }
   > public class LoginUserDetailsDeserializer extends JsonDeserializer<LoginUserDetails> {
   >     private static final Logger logger = LoggerFactory.getLogger(LoginUserDetailsDeserializer.class);
   > 
   >     private static final TypeReference<Set<SimpleGrantedAuthority>> SIMPLE_GRANTED_AUTHORITY_SET = new TypeReference<Set<SimpleGrantedAuthority>>() {
   >     };
   > 
   >     /**
   >      * This method will create {@link LoginUserDetails} object. It will ensure successful object
   >      * creation even if password key is null in serialized json, because credentials may
   >      * be removed from the {@link LoginUserDetails} by invoking {@link LoginUserDetails#eraseCredentials()}. In
   >      * that case there won't be any password key in serialized json.
   >      *
   >      * @param jp   the JsonParser
   >      * @param ctxt the DeserializationContext
   >      * @return the user
   >      * @throws IOException             if a exception during IO occurs
   >      * @throws JsonProcessingException if an error during JSON processing occurs
   >      */
   >     @Override
   >     public LoginUserDetails deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
   >         ObjectMapper mapper = (ObjectMapper) jp.getCodec();
   >         JsonNode jsonNode = mapper.readTree(jp);
   >         Long orgId = readJsonNode(jsonNode, "orgId").asLong();
   >         Long deptId = readJsonNode(jsonNode, "deptId").asLong();
   >         Long userId = readJsonNode(jsonNode, "userId").asLong();
   >         String username = readJsonNode(jsonNode, "username").asText();
   >         Set<? extends GrantedAuthority> authorities = mapper.convertValue(jsonNode.get("authorities"), SIMPLE_GRANTED_AUTHORITY_SET);
   >         boolean enabled = readJsonNode(jsonNode, "enabled").asBoolean();
   >         boolean accountNonExpired = readJsonNode(jsonNode, "accountNonExpired").asBoolean();
   >         boolean credentialsNonExpired = readJsonNode(jsonNode, "credentialsNonExpired").asBoolean();
   >         boolean accountNonLocked = readJsonNode(jsonNode, "accountNonLocked").asBoolean();
   > 
   >         JsonNode passwordNode = readJsonNode(jsonNode, "password");
   >         String password = passwordNode.asText("");
   > 
   >         logger.info("反序列化LoginUserDetails:{}", userId);
   > 
   >         LoginUserDetails result = new LoginUserDetails(
   >                 orgId,
   >                 deptId,
   >                 userId,
   >                 username,
   >                 (Set<GrantedAuthority>) authorities,
   >                 accountNonExpired,
   >                 accountNonLocked,
   >                 credentialsNonExpired,
   >                 enabled,
   >                 password);
   >         if (passwordNode.asText(null) == null) {
   >             result.eraseCredentials();
   >         }
   >         return result;
   >     }
   > 
   >     private JsonNode readJsonNode(JsonNode jsonNode, String field) {
   >         return jsonNode.has(field) ? jsonNode.get(field) : MissingNode.getInstance();
   >     }
   > 
   > }
   > @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
   > @JsonDeserialize(using = LoginUserDetailsDeserializer.class)
   > @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
   >         isGetterVisibility = JsonAutoDetect.Visibility.NONE)
   > @JsonIgnoreProperties(ignoreUnknown = true)
   > public abstract class LoginUserDetailsMixin {
   > }
   > 
   > 
   > public class LoginUserObjectMapperCodecCustomer implements ObjectMapperCodecCustomer {
   >     @Override
   >     public void customize(ObjectMapperCodec objectMapperCodec) {
   >         objectMapperCodec.addModule(new LoginUserModule());
   >         // objectMapperCodec.configureMapper(new Consumer<ObjectMapper>() {
   >         //     @Override
   >         //     public void accept(ObjectMapper objectMapper) {
   >         //         objectMapper.addMixIn(LoginUserDetails.class, LoginUserDetailsMixin.class);
   >         //     }
   >         // });
   >     }
   > 
   >     public static class LoginUserModule extends SimpleModule {
   >         public LoginUserModule() {
   >             super(LoginUserModule.class.getName(), new Version(1, 0, 0, null, null, null));
   >         }
   > 
   >         @Override
   >         public void setupModule(SetupContext context) {
   >             // SecurityJackson2Modules.enableDefaultTyping(context.getOwner());
   >             context.setMixInAnnotations(LoginUserDetails.class, LoginUserDetailsMixin.class);
   >             // context.setMixInAnnotations(User.class, UserMixin.class);
   >         }
   >     }
   > }
   > 
   > // 文件:src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.spring.security.jackson.ObjectMapperCodecCustomer
   > loginUserObjectMapperCodecCustomer=com.houkunlin.login.LoginUserObjectMapperCodecCustomer
   > ```
   
    直接实现接口或者继承对于序列方式差异不大,测试了以上代码,序列化和反序列化没有问题。dubbo 上下文在传递spring security content上下文信息时,传递的是Authentication对象,登录后再次调用序列化出现错误,检查下你上文实现传递的Authentication中的对象信息,是否是你真正需要序列化对象信息。你看能否提供可复现的demo,更易于排查。


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org


[GitHub] [dubbo] jojocodeX commented on issue #12073: 与 SpringSecurity 合并使用时,使用自定义的 UserDetails 对象,用户登录成功后无法发起请求

Posted by "jojocodeX (via GitHub)" <gi...@apache.org>.
jojocodeX commented on issue #12073:
URL: https://github.com/apache/dubbo/issues/12073#issuecomment-1505284335

   > * [ ]  I have searched the [issues](https://github.com/apache/dubbo/issues) of this repository and believe that this is not a duplicate.
   > 
   > ### Environment
   > * Dubbo version: 3.2.0-beta.6   /  org.apache.dubbo:dubbo-bom:3.2.0-beta.6
   > * Java version: java 17
   > * springboot 3.0.5
   > * org.springframework.cloud:spring-cloud-dependencies:2022.0.1
   > * com.alibaba.cloud:spring-cloud-alibaba-dependencies:2022.0.0.0-RC1
   > * com.alibaba.fastjson2:fastjson2:2.0.27
   > 
   > ### Steps to reproduce this issue
   > 1. Dubbo请求获取用户信息
   > 2. 返回自定义的UserDetails对象,登录成功
   > 3. Dubbo再次请求获取用户信息
   > 4. 控制台报错
   > 
   > 自定义一个 UserDetails 对象,在SpringBootSecurity登录成功后返回自定义的 UserDetails 对象,此时再次发起Dubbo请求,无法获取数据,控制台报错。
   > 
   > ```
   > 2023-04-11T22:54:15.413+08:00  WARN 64592 --- [o-auto-1-exec-3] o.a.d.r.c.s.wrapper.MockClusterInvoker   :  [DUBBO] fail-mock: getLocalIdentifier fail-mock enabled , url : consumer://172.29.237.2/com.houkunlin.cloud.micro.rpc.UserDubboService?application=api-auth-server&background=false&check=true&dubbo=2.0.2&executor-management-mode=default&file-cache=false&interface=com.houkunlin.cloud.micro.rpc.UserDubboService&methods=getAssignAuthorities,getLeaderIds,getLocalIdentifier,getUserAllPermissionValues,getUserByUserId,getUserByUsername,loginFailureAction,loginSuccessAction,saveUserLog,updatePassword&mock=true&pid=64592&qos.enable=true&qos.port=9622&register-mode=instance&register.ip=172.29.237.2&release=3.2.0-beta.6&revision=0.0.7-SNAPSHOT-plain&side=consumer&sticky=false&timestamp=1681224224385&unloadClusterRelated=false, dubbo version: 3.2.0-beta.6, current host: 172.29.237.2, error code: 2-17. This may be caused by failed to mock invoke, go to https://dubbo.apache.org/faq/2/17 
 to find instructions. 
   > 
   > org.apache.dubbo.rpc.RpcException: Failed to invoke the method getLocalIdentifier in the service com.houkunlin.cloud.micro.rpc.UserDubboService. Tried 3 times of the providers [172.29.237.2:20883] (1/1) from the registry 192.168.0.5:8848 on the consumer 172.29.237.2 using the dubbo version 3.2.0-beta.6. Last error is: Failed to invoke remote method: getLocalIdentifier, provider: DefaultServiceInstance{serviceName='system-user-server', host='172.29.237.2', port=20883, enabled=true, healthy=true, metadata={dubbo.metadata-service.url-params={"prefer.serialization":"fastjson2,hessian2","version":"1.0.0","dubbo":"2.0.2","release":"3.2.0-beta.6","side":"provider","port":"20883","protocol":"dubbo"}, dubbo.endpoints=[{"port":20883,"protocol":"dubbo"}], dubbo.metadata.revision=998f69ef376ecb6920e7f05d9e6f0b14, dubbo.metadata.storage-type=local, timestamp=1681209402712}}, service{name='com.houkunlin.cloud.micro.rpc.UserDubboService',group='null',version='null',protocol='dubbo',port='20883
 ',params={executor-management-mode=default, side=provider, file-cache=false, release=3.2.0-beta.6, methods=getAssignAuthorities,getLeaderIds,getLocalIdentifier,getUserAllPermissionValues,getUserByUserId,getUserByUsername,loginFailureAction,loginSuccessAction,saveUserLog,updatePassword, deprecated=false, dubbo=2.0.2, interface=com.houkunlin.cloud.micro.rpc.UserDubboService, service-name-mapping=true, register-mode=instance, generic=false, revision=0.0.7-SNAPSHOT-plain, application=system-user-server, prefer.serialization=fastjson2,hessian2, background=false, dynamic=true, anyhost=true},}, cause: org.apache.dubbo.remoting.RemotingException: java.lang.RuntimeException: objectMapper! deserialize error java.lang.IllegalArgumentException: The class with com.houkunlin.cloud.micro.login.LoginUserDetails and name of com.houkunlin.cloud.micro.login.LoginUserDetails is not in the allowlist. If you believe this class is safe to deserialize, please provide an explicit mapping using Jackson annot
 ations or by providing a Mixin. If the serialization is only done by a trusted source, you can also enable default typing. See https://github.com/spring-projects/spring-security/issues/4370 for details
   > java.lang.RuntimeException: objectMapper! deserialize error java.lang.IllegalArgumentException: The class with com.houkunlin.cloud.micro.login.LoginUserDetails and name of com.houkunlin.cloud.micro.login.LoginUserDetails is not in the allowlist. If you believe this class is safe to deserialize, please provide an explicit mapping using Jackson annotations or by providing a Mixin. If the serialization is only done by a trusted source, you can also enable default typing. See https://github.com/spring-projects/spring-security/issues/4370 for details
   > 	at org.apache.dubbo.spring.security.jackson.ObjectMapperCodec.deserialize(ObjectMapperCodec.java:50)
   > 	at org.apache.dubbo.spring.security.jackson.ObjectMapperCodec.deserialize(ObjectMapperCodec.java:58)
   > 	at org.apache.dubbo.spring.security.filter.ContextHolderAuthenticationResolverFilter.getSecurityContext(ContextHolderAuthenticationResolverFilter.java:56)
   > 	at org.apache.dubbo.spring.security.filter.ContextHolderAuthenticationResolverFilter.invoke(ContextHolderAuthenticationResolverFilter.java:45)
   > 	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   > 	at org.apache.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.java:192)
   > 	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   > 	at org.apache.dubbo.rpc.filter.ClassLoaderFilter.invoke(ClassLoaderFilter.java:54)
   > 	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   > 	at org.apache.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.java:41)
   > 	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   > 	at org.apache.dubbo.rpc.filter.ProfilerServerFilter.invoke(ProfilerServerFilter.java:64)
   > 	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   > 	at org.apache.dubbo.rpc.filter.ContextFilter.invoke(ContextFilter.java:144)
   > 	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:331)
   > 	at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CallbackRegistrationInvoker.invoke(FilterChainBuilder.java:194)
   > 	at org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol$1.reply(DubboProtocol.java:159)
   > 	at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.java:103)
   > 	at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:186)
   > 	at org.apache.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:53)
   > 	at org.apache.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:62)
   > 	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
   > 	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
   > 	at org.apache.dubbo.common.threadlocal.InternalRunnable.run(InternalRunnable.java:41)
   > 	at java.base/java.lang.Thread.run(Thread.java:833)
   > ```
   > 
   > 尝试使用 `ObjectMapperCodecCustomer` 来处理 ObjectMapperCodec.ObjectMapper ,增加`context.setMixInAnnotations(LoginUserDetails.class, LoginUserDetailsMixin.class);`,断点发现配置正常生效,在Dubbo请求之前断点能够看到生效的信息,但是依旧无法完成反序列化,并且控制台报错的位置在调试模式无法断点。
   > 
   > 复制 `CoreJackson2Module` 类到本地进行覆盖,取消 `// context.setMixInAnnotations(User.class, UserMixin.class);`配置,使用官方的 User 对象,调试运行发现本地 `CoreJackson2Module` 正常执行,并且ObjectMapperCodec.ObjectMapper无UserMixin配置,此时依旧能够请求成功,但是我想要的并不是使用官方的User对象,而是想要自定义的UserDetails对象。
   > 
   > 上面两种方式,一种是增加自己的 Mixin 对象,一种是取消官方的 Mixin 对象配置,两种方式均无法正常生效,虽然断点看到的配置是生效的,但是实际Dubbo请求时执行的配置与断点的配置不一致
   > 
   > Pls. provide [GitHub address] to reproduce this issue.
   > 
   > ### Expected Behavior
   > ### Actual Behavior
   > If there is an exception, please attach the exception trace:
   > 
   > ```
   > Just put your stack trace here!
   > ```
   
   在本地进行了相应的自定义序列化器,没有复现该错误,麻烦你提供下相关的代码
   
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org


[GitHub] [dubbo] houkunlin commented on issue #12073: 与 SpringSecurity 合并使用时,使用自定义的 UserDetails 对象,用户登录成功后无法发起请求

Posted by "houkunlin (via GitHub)" <gi...@apache.org>.
houkunlin commented on issue #12073:
URL: https://github.com/apache/dubbo/issues/12073#issuecomment-1505570335

   在我整理复现Demo的时候发现了问题所在了。目前已经解决了。
   我有两个服务,auth-server / user-server(provider),发现 auth-server 调用 user-server 的时候,属于 user-server 的异常,但是打印在了 auth-server 的控制台,导致我一直以为是 auth-server 的错误问题,因此没有重启 user-server 服务,也就导致我的一些更改没有在 user-server 生效,但是 user-server 控制台一直没有错误内容,只有 auth-server 有错误内容,从而忽略了 user-server 的问题


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org


[GitHub] [dubbo] houkunlin commented on issue #12073: 与 SpringSecurity 合并使用时,使用自定义的 UserDetails 对象,用户登录成功后无法发起请求

Posted by "houkunlin (via GitHub)" <gi...@apache.org>.
houkunlin commented on issue #12073:
URL: https://github.com/apache/dubbo/issues/12073#issuecomment-1505336399

   @jojocodeX  我这两天把我代码提取一下,尽量提供一个复现的完整代码出来。
   目前与你贴出的代码有一点区别,我的 LoginUserDetails 是直接实现了接口,而不是继承 `public class LoginUserDetails implements UserDetails, CredentialsContainer`。下面先放一下我的几个类的代码,完整的简化复现版本,需要多花点时间来搞。
   
   1. SpringBootSecurity第一次请求 `org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername` 方法发起 Dubbo 调用时,能够正常返回信息,此时多次调用 Dubbo 获取数据都正常
   2. 当登录成功后,在 `org.springframework.security.web.authentication.AuthenticationSuccessHandler` 再次发起一次 Dubbo 调用就会报错
   
   ```java
   @JsonDeserialize(using = LoginUserDetailsDeserializer.class)
   @Getter
   @EqualsAndHashCode
   @Accessors(fluent = true)
   public class LoginUserDetails implements UserDetails, CredentialsContainer {
   
       private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
       /**
        * 机构ID
        */
       private final Long orgId;
       /**
        * 部门ID
        */
       private final Long deptId;
       /**
        * 用户ID
        */
       private final Long userId;
       /**
        * 用户名,实际存储的是用户ID
        */
       private final String username;
       /**
        * 权限代码列表
        */
       private final Set<GrantedAuthority> authorities;
       /**
        * 账号未过期
        */
       private final boolean accountNonExpired;
       /**
        * 账号未锁定
        */
       private final boolean accountNonLocked;
       /**
        * 密码未过期
        */
       private final boolean credentialsNonExpired;
       /**
        * 是否启用
        */
       private final boolean enabled;
       /**
        * 用户密码
        */
       private String password;
   
       public LoginUserDetails(final LoginUserVo user, final String credential, final Set<String> permissions) {
           this.username = ObjectUtils.getDisplayString(user.getId());
           this.password = credential;
           this.enabled = user.isEnabled();
           this.accountNonExpired = !user.isExpired();
           this.credentialsNonExpired = true;
           this.accountNonLocked = true;
           this.authorities = permissions.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toSet());
           this.orgId = user.getOrgId();
           this.deptId = user.getDeptId();
           this.userId = user.getId();
       }
   
       public LoginUserDetails(Long orgId, Long deptId, Long userId, String username, Set<GrantedAuthority> authorities,
                               boolean accountNonExpired, boolean accountNonLocked, boolean credentialsNonExpired,
                               boolean enabled, String password) {
           this.orgId = orgId;
           this.deptId = deptId;
           this.userId = userId;
           this.username = username;
           this.authorities = authorities;
           this.accountNonExpired = accountNonExpired;
           this.accountNonLocked = accountNonLocked;
           this.credentialsNonExpired = credentialsNonExpired;
           this.enabled = enabled;
           this.password = password;
       }
   
       @Override
       public void eraseCredentials() {
           this.password = null;
       }
   
       @Override
       public Collection<? extends GrantedAuthority> getAuthorities() {
           return authorities;
       }
   
       @Override
       public String getPassword() {
           return password;
       }
   
       @Override
       public String getUsername() {
           return username;
       }
   
       @Override
       public boolean isAccountNonExpired() {
           return accountNonExpired;
       }
   
       @Override
       public boolean isAccountNonLocked() {
           return accountNonLocked;
       }
   
       @Override
       public boolean isCredentialsNonExpired() {
           return credentialsNonExpired;
       }
   
       @Override
       public boolean isEnabled() {
           return enabled;
       }
   }
   public class LoginUserDetailsDeserializer extends JsonDeserializer<LoginUserDetails> {
       private static final Logger logger = LoggerFactory.getLogger(LoginUserDetailsDeserializer.class);
   
       private static final TypeReference<Set<SimpleGrantedAuthority>> SIMPLE_GRANTED_AUTHORITY_SET = new TypeReference<Set<SimpleGrantedAuthority>>() {
       };
   
       /**
        * This method will create {@link LoginUserDetails} object. It will ensure successful object
        * creation even if password key is null in serialized json, because credentials may
        * be removed from the {@link LoginUserDetails} by invoking {@link LoginUserDetails#eraseCredentials()}. In
        * that case there won't be any password key in serialized json.
        *
        * @param jp   the JsonParser
        * @param ctxt the DeserializationContext
        * @return the user
        * @throws IOException             if a exception during IO occurs
        * @throws JsonProcessingException if an error during JSON processing occurs
        */
       @Override
       public LoginUserDetails deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
           ObjectMapper mapper = (ObjectMapper) jp.getCodec();
           JsonNode jsonNode = mapper.readTree(jp);
           Long orgId = readJsonNode(jsonNode, "orgId").asLong();
           Long deptId = readJsonNode(jsonNode, "deptId").asLong();
           Long userId = readJsonNode(jsonNode, "userId").asLong();
           String username = readJsonNode(jsonNode, "username").asText();
           Set<? extends GrantedAuthority> authorities = mapper.convertValue(jsonNode.get("authorities"), SIMPLE_GRANTED_AUTHORITY_SET);
           boolean enabled = readJsonNode(jsonNode, "enabled").asBoolean();
           boolean accountNonExpired = readJsonNode(jsonNode, "accountNonExpired").asBoolean();
           boolean credentialsNonExpired = readJsonNode(jsonNode, "credentialsNonExpired").asBoolean();
           boolean accountNonLocked = readJsonNode(jsonNode, "accountNonLocked").asBoolean();
   
           JsonNode passwordNode = readJsonNode(jsonNode, "password");
           String password = passwordNode.asText("");
   
           logger.info("反序列化LoginUserDetails:{}", userId);
   
           LoginUserDetails result = new LoginUserDetails(
                   orgId,
                   deptId,
                   userId,
                   username,
                   (Set<GrantedAuthority>) authorities,
                   accountNonExpired,
                   accountNonLocked,
                   credentialsNonExpired,
                   enabled,
                   password);
           if (passwordNode.asText(null) == null) {
               result.eraseCredentials();
           }
           return result;
       }
   
       private JsonNode readJsonNode(JsonNode jsonNode, String field) {
           return jsonNode.has(field) ? jsonNode.get(field) : MissingNode.getInstance();
       }
   
   }
   @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
   @JsonDeserialize(using = LoginUserDetailsDeserializer.class)
   @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
           isGetterVisibility = JsonAutoDetect.Visibility.NONE)
   @JsonIgnoreProperties(ignoreUnknown = true)
   public abstract class LoginUserDetailsMixin {
   }
   
   
   public class LoginUserObjectMapperCodecCustomer implements ObjectMapperCodecCustomer {
       @Override
       public void customize(ObjectMapperCodec objectMapperCodec) {
           objectMapperCodec.addModule(new LoginUserModule());
           // objectMapperCodec.configureMapper(new Consumer<ObjectMapper>() {
           //     @Override
           //     public void accept(ObjectMapper objectMapper) {
           //         objectMapper.addMixIn(LoginUserDetails.class, LoginUserDetailsMixin.class);
           //     }
           // });
       }
   
       public static class LoginUserModule extends SimpleModule {
           public LoginUserModule() {
               super(LoginUserModule.class.getName(), new Version(1, 0, 0, null, null, null));
           }
   
           @Override
           public void setupModule(SetupContext context) {
               // SecurityJackson2Modules.enableDefaultTyping(context.getOwner());
               context.setMixInAnnotations(LoginUserDetails.class, LoginUserDetailsMixin.class);
               // context.setMixInAnnotations(User.class, UserMixin.class);
           }
       }
   }
   
   // 文件:src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.spring.security.jackson.ObjectMapperCodecCustomer
   loginUserObjectMapperCodecCustomer=com.houkunlin.login.LoginUserObjectMapperCodecCustomer
   
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org


[GitHub] [dubbo] AlbumenJ commented on issue #12073: 与 SpringSecurity 合并使用时,使用自定义的 UserDetails 对象,用户登录成功后无法发起请求

Posted by "AlbumenJ (via GitHub)" <gi...@apache.org>.
AlbumenJ commented on issue #12073:
URL: https://github.com/apache/dubbo/issues/12073#issuecomment-1505129964

   @jojocodeX PTAL


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org