在Spring security oauth中集成异常处理

时间:2016-08-24 12:04:57

标签: spring authentication spring-security exception-handling spring-security-oauth2

我已经实现了spring security oauth来验证我的应用程序。从客户端应用程序(Android应用程序)我想使用资源所有者密码凭据授权类型为用户检索令牌。如果给出了错误的凭证我扔了 我的自定义UserDetailsS​​ervice中的UsernameNotFoundException异常,但在我的客户端应用程序中,我没有得到正确的错误响应。我认为服务器返回RuntimeException,因此没有形成正确的响应。你能告诉我在这种情况下我能做些什么吗?我应该如何为此设置Spring Security ExceptionHandler?这是我进入服务器的例外。

      org.apache.catalina.core.StandardWrapperValve invoke
  SEVERE: Servlet.service() for servlet [MyProject] in context with path [/MyProject] threw exception [Handler processing failed; nested exception is java.lang.StackOverflowError] with root cause
  java.lang.StackOverflowError
    at sun.nio.cs.UTF_8.updatePositions(UTF_8.java:77)
    at sun.nio.cs.UTF_8.access$200(UTF_8.java:57)
    at sun.nio.cs.UTF_8$Encoder.encodeArrayLoop(UTF_8.java:636)
    at sun.nio.cs.UTF_8$Encoder.encodeLoop(UTF_8.java:691)
    at java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:579)
    at sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:271)
    at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:125)
    at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:135)
    at java.io.OutputStreamWriter.write(OutputStreamWriter.java:220)
    at java.io.Writer.write(Writer.java:157)
    at com.google.gson.stream.JsonWriter.string(JsonWriter.java:534)
    at com.google.gson.stream.JsonWriter.writeDeferredName(JsonWriter.java:402)
    at com.google.gson.stream.JsonWriter.value(JsonWriter.java:417)
    at com.google.gson.internal.bind.TypeAdapters$13.write(TypeAdapters.java:362)
    at com.google.gson.internal.bind.TypeAdapters$13.write(TypeAdapters.java:346)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
       .....................

以下是我的代码。

spring-security.xml:

            <?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
      xmlns:context="http://www.springframework.org/schema/context"
      xmlns:sec="http://www.springframework.org/schema/security" xmlns:mvc="http://www.springframework.org/schema/mvc"
      xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
            http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd ">


      <http pattern="/oauth/token" create-session="stateless"  authentication-manager-ref="authenticationManager"
            xmlns="http://www.springframework.org/schema/security" > 

            <intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" method="POST" />
            <anonymous enabled="false" />
            <http-basic entry-point-ref="clientAuthenticationEntryPoint" />
            <custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" /> 
            <access-denied-handler ref="oauthAccessDeniedHandler" />
      </http>

      <http pattern="/protected/**" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint"
            xmlns="http://www.springframework.org/schema/security">
            <anonymous enabled="false" />
            <intercept-url pattern="/protected/**" method="GET" access="ROLE_APP" />
            <!-- <intercept-url pattern="/resources/**" access="IS_AUTHENTICATED_FULLY" /> -->
            <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
            <access-denied-handler ref="oauthAccessDeniedHandler" />
      </http>

      <http pattern="/logout" create-session="never" 
            entry-point-ref="oauthAuthenticationEntryPoint"
            xmlns="http://www.springframework.org/schema/security">
            <anonymous enabled="false" />
            <intercept-url pattern="/logout" method="GET" />
            <sec:logout invalidate-session="true" logout-url="/logout" success-handler-ref="logoutSuccessHandler"   />
            <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
            <access-denied-handler ref="oauthAccessDeniedHandler" />
      </http>

      <bean id="logoutSuccessHandler" class="com.example.myproject.security.LogoutImpl" >
            <property name="tokenstore" ref="tokenStore"></property>
      </bean>

      <bean id="oauthAuthenticationEntryPoint"
            class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
            <property name="exceptionTranslator" ref="myExceptionTranslator"></property>
      </bean>

  <bean id="myExceptionTranslator"
            class="org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator">
      </bean>

      <bean id="clientAuthenticationEntryPoint"
            class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
            <property name="realmName" value="springsec/client" />
            <property name="typeName" value="Basic" />
      </bean>

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

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

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

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

      <bean id="clientDetails" class="com.example.myproject.service.ClientService"/>

      <authentication-manager id="userAuthenticationManager" 
            xmlns="http://www.springframework.org/schema/security">
            <authentication-provider  user-service-ref="userService">
            </authentication-provider>
      </authentication-manager>

      <bean id="userService"
            class="com.example.myproject.service.UserService">
      </bean>

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

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

      <!-- <bean id="tokenStore"
            class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore" /> -->

      <bean id="tokenStore"
          class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore" >
            <property name="authenticationKeyGenerator">
                  <bean class="com.example.myproject.service.UniqueAuthenticationKeyGenerator" />
            </property> 
     </bean>

      <bean id="tokenServices" 
            class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
            <property name="tokenStore" ref="tokenStore" />
            <property name="supportRefreshToken" value="true" />
            <property name="accessTokenValiditySeconds" value="300000"></property>
            <property name="clientDetailsService" ref="clientDetails" />
            <property name="tokenEnhancer"><bean class="com.example.myproject.service.CustomTokenEnhancer" /></property>
      </bean>

      <sec:global-method-security
            pre-post-annotations="enabled" proxy-target-class="true">
            <!--you could also wire in the expression handler up at the layer of the 
                  http filters. See https://jira.springsource.org/browse/SEC-1452 -->
            <sec:expression-handler ref="oauthExpressionHandler" />
      </sec:global-method-security>

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

</beans>

ClientService.java:

            @Component
public class ClientService implements ClientDetailsService {

    @Autowired
    private OauthRepository oauthRepository;

    @Override
    public ClientDetails loadClientByClientId(String s) throws ClientRegistrationException{
        BaseClientDetails clientDetails = oauthRepository.getByClientId(s);
              return clientDetails;

    }
}

UserService.java:

            @Component
public class UserService implements UserDetailsService {

    @Autowired
    private OauthRepository oauthRepository;

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
      UserDetails user = oauthRepository.getByUsername(s);
              return user;

    }
}

OauthRepository.java:

            @Repository
@Transactional
public class OauthRepository {

      @Autowired
      private SessionFactory sessionFactory;

      @Autowired
      private InMemoryTokenStore tokenStore;

      private org.hibernate.Session getCurrentSession(){
            return sessionFactory.getCurrentSession();
      }



    public UserDetails getByUsername(String username) {

            MyUser user=new MyUser();
            user.setUserName(username);
            Query query=getCurrentSession().createQuery("FROM User WHERE userName=:usrName");
            query.setParameter("usrName", username);
            List<SiUser> getUser=query.list();

            User act=getUser.get(0);
            user.setPassword(act.getPassword());
            user.setUserId(act.getUserId());
            user.setAuthorities(getAuthorities(act.getUserId()));

            return user;
    }

    public BaseClientDetails getByClientId(String clientId) {
      System.out.println(" *** OauthRepository.getByClientId "+clientId);

      Query query=getCurrentSession().createQuery("FROM OauthClientDetails WHERE clientId=:clientId");
            query.setParameter("clientId", clientId);
            List<OauthClientDetails> getClient=query.list();

            OauthClientDetails oauthClient=getClient.get(0);
            BaseClientDetails details = new BaseClientDetails();
            details.setClientId(oauthClient.getClientId());
            List<String> grantTypesList = Arrays.asList(oauthClient.getAuthorizedGrantTypes().split(","));
            details.setAuthorizedGrantTypes(grantTypesList); 
            details.setClientSecret(oauthClient.getClientSecret());

        return details;


    }

/**
 * Retrieves a collection of {@link GrantedAuthority} based on a numerical role
 * @param role the numerical role
 * @return a collection of {@link GrantedAuthority
 */
public Collection<GrantedAuthority> getAuthorities(Integer role) {
      List<GrantedAuthority> authList = getGrantedAuthorities(getRoles(role));
      return authList;
}
/**
 * Converts a numerical role to an equivalent list of roles
 * @param role the numerical role
 * @return list of roles as as a list of {@link String}
 */
public List<String> getRoles(Integer role) {
      List<String> roles = new ArrayList<String>();

      Query query=getCurrentSession().createQuery("FROM UserRole WHERE userID=:userId");
      query.setParameter("userId", role);
      List<SiUserRole> getUser=query.list();

      UserRole actRole=getUser.get(0);
      roles.add(actRole.getRole());
      return roles;
}
/**
 * Wraps {@link String} roles to {@link SimpleGrantedAuthority} objects
 * @param roles {@link String} of roles
 * @return list of granted authorities
 */
public static List<GrantedAuthority> getGrantedAuthorities(List<String> roles) {
      List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
      for (String role : roles) {
            authorities.add(new GrantedAuthorityImpl(role));
      }
      return authorities;
}


}

servlet-context.xml:

            <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
      xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
      xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
  http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
      <!-- @author Nagesh.Chauhan(neel4soft@gmail.com) -->
      <context:annotation-config />
    <context:component-scan base-package="com.example.myproject" />
      <mvc:annotation-driven />

      <bean id="multipartResolver"
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">      

    <!-- one of the properties available; the maximum file size in bytes -->
     <property name="maxUploadSize" value="1000000000" />
      </bean>      

      <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/MyDatabase"/>
    <property name="username" value="username"/>
    <property name="password" value="password"/>
    <property name="validationQuery" value="SELECT 1"/>
  </bean>

  <!-- Hibernate Session Factory -->
  <bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="myDataSource"/>
    <property name="packagesToScan">
      <array>
        <value>com.example.myproject</value>
      </array>
    </property>
    <property name="hibernateProperties">
      <value>
        hibernate.dialect=org.hibernate.dialect.MySQLDialect
      </value>
    </property>
  </bean>
  <!-- Hibernate Transaction Manager -->
  <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="mySessionFactory"/>
  </bean>

  <!-- Activates annotation based transaction management -->
  <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

0 个答案:

没有答案