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

Spring Security Oauth2资源所有者密码流:当我发送REST请求时,我的用户详细信息服务总是获得客户端id而不是用户名

阎裕
2023-03-14

因此,我尝试向我的oauth服务器发送一个请求(没有头):grant_type=password&username=blah&password=blah&client_id=blahblah。

我有两个身份验证管理器(一个用于客户端,另一个用于用户验证)。问题是,我的任何身份验证管理器都没有传递用户名进行验证。在这两种情况下,都使用client_id调用它们。我想要的是一个验证客户端,另一个验证用户。

我的bean配置是这样的:

 <http pattern="/oauth/token" create-session="stateless"  authentication-manager-ref="authenticationManager" xmlns="http://www.springframework.org/schema/security">
    <intercept-url pattern="/oauth/token" access="ROLE_USER" />
    <anonymous enabled="false" />
    <http-basic entry-point-ref="clientAuthenticationEntryPoint" />

    <custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />  

    <access-denied-handler ref="oauthAccessDeniedHandler" />
</http>


<!-- The OAuth2 protected resources are separated out into their own block so we can deal with authorization and error handling 
    separately. This isn't mandatory, but it makes it easier to control the behaviour. -->
<http pattern="/api/**" create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint"
    access-decision-manager-ref="accessDecisionManager" xmlns="http://www.springframework.org/schema/security">
    <anonymous enabled="false" />
    <intercept-url pattern="/api" access="ROLE_USER,SCOPE_READ" />

    <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
    <access-denied-handler ref="oauthAccessDeniedHandler" />
</http>


<authentication-manager  alias="authenticationManager"  xmlns="http://www.springframework.org/schema/security">
    <sec:authentication-provider user-service-ref="clientDetailsUserService" />
    <sec:authentication-provider user-service-ref="customUserDetailService">
        <sec:password-encoder ref="passwordEncoder" />
    </sec:authentication-provider>
</authentication-manager>


<beans:bean id="customUserDetailService" class="com.cointraders.api.securities.UserDetailsServiceImpl" />


<beans:bean id="clientDetails" class="org.springframework.security.oauth2.provider.JdbcClientDetailsService">
    <beans:constructor-arg ref="dataSource" />
</beans:bean>

<beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased" xmlns="http://www.springframework.org/schema/beans">
    <beans:constructor-arg>
        <beans:list>
            <beans:bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" />
            <beans:bean class="org.springframework.security.access.vote.RoleVoter" />
            <beans:bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
        </beans:list>
    </beans:constructor-arg>
</beans:bean>

<oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices">
    <oauth:refresh-token />
    <oauth:password authentication-manager-ref="authenticationManager"  />
</oauth:authorization-server>


<oauth:resource-server id="resourceServerFilter" resource-id="api" token-services-ref="tokenServices" />

<sec:global-method-security pre-post-annotations="enabled" proxy-target-class="true">
    <sec:expression-handler ref="oauthExpressionHandler" />
</sec:global-method-security>

<oauth:expression-handler id="oauthExpressionHandler" />

<oauth:web-expression-handler id="oauthWebExpressionHandler" />

<beans:bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
    <beans:property name="realmName" value="api/" />
</beans:bean>



<beans:bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
    <beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>


<beans:bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.JdbcTokenStore">
    <beans:constructor-arg ref="dataSource" />
</beans:bean>


<beans:bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
    <beans:property name="tokenStore" ref="tokenStore" />
    <beans:property name="supportRefreshToken" value="true" />
    <beans:property name="clientDetailsService" ref="clientDetails" />
</beans:bean>

<beans:bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
    <beans:constructor-arg ref="clientDetails" />
</beans:bean>

<beans:bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />

<beans:bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
    <beans:property name="realmName" value="api" />
</beans:bean>

这是我的web.xml

    <!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
  <filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <param-name>contextAttribute</param-name>
        <param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.spring</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/appServlet/*.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>/</url-pattern>
 </servlet-mapping>

我的用户详细信息服务类

 public class UserDetailsServiceImpl extends PersonServiceImpl implements
    UserDetailsService {

@Override
public UserDetails loadUserByUsername(String username)
        throws UsernameNotFoundException {

    UserDetails details = null;
    Specification<Person> specs = Specifications.where(PersonSpecification.equalsUserName(username));
    Person person = this.personRepository.findOne(specs);
    if(person!=null)
    {   
        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        authorities.add(new   SimpleGrantedAuthority(person.getRole().getRole().name()));
        details = new User(person.getUserName(), person.getPassword(), person.getActive(), false, false, false, authorities);
    }
    return details;
 }

 }

共有1个答案

黄丰
2023-03-14

中,您没有在 授予类型中设置authenticationmanager(因此它使用默认bean名称“authenticationmanager”,您已将其映射到客户端凭据)。

另外一个问题是,您两次使用 ,但没有为其中任何一个指定显式的“id=”,这实际上只定义了一个authenticationmanager,因为第二个authenticationmanager覆盖了第一个authenticationmanager(它们都具有相同的id)。尝试使用“id=”而不是“alias=”。

如果可以的话,您确实需要在头中发送客户机凭据(但您可能知道这一点)。

 类似资料:
  • 我尝试通过遵循spring sparklr2示例来设置一个OAuth2服务器。我将其修改为使用数据库UserDetailsService。当我尝试用curl交换带有密码的令牌时,如下所示: 它在加载用户findByUsername()时失败,当我查看代码时,它使用client-id(在我的例子中是'client1')作为用户名。调用堆栈为:DaoAuthenticationProvider.ret

  • 问题内容: 所以现在,我正在制作一个基于客户端服务器应用程序的多线程。在服务器端,我为接受的每个连接创建了一个线程。 在线程类中,我创建了一种将命令发送到客户端的方法。我只想要的是如何将参数发送到所有正在运行的客户端?为简单起见,我只想使此服务器向所有连接的客户端发送消息。 我已经阅读了这篇文章,并从此链接中找到方法。但是,当我尝试使用自己的代码时,中没有类似的方法。 好的,这是我的服务器和线程示

  • 上下文: > 我的软件应用程序是一个多租户应用程序,客户可以登录到该应用程序并生成他们自己的客户端,以便与资源所有者密码流OAuth请求一起使用。 我们的OAuth2.0授权服务器构建在WebAPI中,并继承自Microsoft提供的Microsoft.Owin.Security.OAuth.OAuthAuthorizationServerProvider类。目前,我们只支持一个流(资源所有者密码

  • 我有一个netty服务器和客户端在项目中,希望他们之间交换消息。 服务器处理程序代码: 客户端处理程序代码: MessageDecoder代码: 服务器输出如下: 客户端输出如下: 所以从日志的输出可以看出,客户端向服务器端发送了10条消息,而服务器端只接收到一条消息。我的代码有什么问题吗?我想也许是我误用的原物?

  • 当我在accessTokenUri中提供域名时,它不起作用并报告错误,但当我提供localhost时,它起作用。为什么? 授权服务器Config.java ResourceServerConfig.java 错误: 2018-09-14 12:00:13.083信息25836---[main]o.s.j.e.a。AnnotationMBeanExporter:Located managed bea

  • 我在Amazon EC2上设置了一个2节点hazelcast集群。在其中一个节点上,我有一个连接到集群并运行原子长计数器增量的客户端程序 如何找出客户端连接并运行增量AndGet操作的Hazelcast服务器节点? 谢谢