CustomAuthenticationProvider не вызывается после перехода на Spring Security 5 - PullRequest
0 голосов
/ 02 августа 2020

При миграции возникает много проблем, раньше я использовал Spring boot 1.5 и Spring Security 4. Пользовательская аутентификация здесь не вызывается. Если я использую вместо того Затем будет вызываться customAuthentication manager, но аутентификация класса ProviderManager вызывается несколько раз.

Но это исходный файл, который отлично работает в случае весенней безопасности 4 и весенней загрузки 2.

ApplicationContext-securtity. xml Файл

<beans:beans xmlns="http://www.springframework.org/schema/security"
             xmlns:beans="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:oauth2="http://www.springframework.org/schema/security/oauth2"
             xmlns:jdbc="http://www.springframework.org/schema/jdbc"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/security
            http://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">

<http pattern="/api-docs/**" security="none"
        xmlns="http://www.springframework.org/schema/security">
    </http>

    <!-- Login/Logout -->
    <http pattern="/eventapp/logout*" create-session="never"
        entry-point-ref="oauthAuthenticationEntryPoint"
        access-decision-manager-ref="accessDecisionManager"
        xmlns="http://www.springframework.org/schema/security">
        <anonymous enabled="false" />
        <intercept-url pattern="/eventapp/logout*" access="hasAnyRole('ROLE_PLANNER','ROLE_PERFORMER')" />

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

    <http pattern="/oauth/token" create-session="stateless"
        authentication-manager-ref="clientAuthenticationManager"

        xmlns="http://www.springframework.org/schema/security">
        <intercept-url pattern="/oauth/token" access="isFullyAuthenticated()"/>
        <anonymous enabled="false" />
        <http-basic entry-point-ref="clientAuthenticationEntryPoint"  />
        <!-- include this only if you need to authenticate clients via request
            parameters -->
        <custom-filter ref="clientCredentialsTokenEndpointFilter"
            after="BASIC_AUTH_FILTER"  />
        <access-denied-handler ref="oauthAccessDeniedHandler" />
        <csrf disabled="true"/>
        <headers disabled="true"/>


    </http>

    <!--  signuptag-->

    <http pattern="/eventapp/performer/signup*" security="none"
        xmlns="http://www.springframework.org/schema/security">
    </http>
    <http pattern="/eventapp/performer/signup/*" security="none"
        xmlns="http://www.springframework.org/schema/security">
    </http>

    <http pattern="/eventapp/planner/signup*" security="none"
        xmlns="http://www.springframework.org/schema/security">
    </http>
    <http pattern="/eventapp/planner/signup/*" security="none"
        xmlns="http://www.springframework.org/schema/security">
    </http>

    <!-- Utilitytag -->
    <http pattern="/eventapp/utility/country*" security="none"
        xmlns="http://www.springframework.org/schema/security">
    </http>

    <!-- Performance Request controller -->

    <http pattern="/eventapp/performanceRequest/getAllPerformanceRequest*" security="none"
        xmlns="http://www.springframework.org/schema/security">
    </http>

    <http pattern="/eventapp/performanceRequest/post" create-session="never"
        entry-point-ref="oauthAuthenticationEntryPoint"
        access-decision-manager-ref="accessDecisionManager"
        xmlns="http://www.springframework.org/schema/security">
        <anonymous enabled="false" />
        <intercept-url pattern="/eventapp/performanceRequest/post" access="hasAuthority('ROLE_PLANNER')" />

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

    <http pattern="/eventapp/performanceRequest/plannerPerformanceRequest*" create-session="never"
        entry-point-ref="oauthAuthenticationEntryPoint"
        access-decision-manager-ref="accessDecisionManager"
        xmlns="http://www.springframework.org/schema/security">
        <anonymous enabled="false" />
        <intercept-url pattern="/eventapp/performanceRequest/plannerPerformanceRequest*" access="hasAuthority('ROLE_PLANNER')" />
        <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
        <access-denied-handler ref="oauthAccessDeniedHandler"  />
        <csrf disabled="true"/>
    </http>

    <http pattern="/eventapp/planner/mobileNumberVerification/*" create-session="never"
        entry-point-ref="oauthAuthenticationEntryPoint"
        access-decision-manager-ref="accessDecisionManager"
        xmlns="http://www.springframework.org/schema/security">
        <anonymous enabled="false" />
        <intercept-url pattern="/eventapp/planner/mobileNumberVerification/*" access="hasAuthority('ROLE_PLANNER')" />
        <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
        <access-denied-handler ref="oauthAccessDeniedHandler"  />
        <csrf disabled="true"/>
    </http>

<!--    <http pattern="/eventapp/planner/*" create-session="never"  -->
<!--        entry-point-ref="oauthAuthenticationEntryPoint" -->
<!--        access-decision-manager-ref="accessDecisionManager" -->
<!--        xmlns="http://www.springframework.org/schema/security"> -->
<!--        <anonymous enabled="false" /> -->
<!--        <intercept-url pattern="/eventapp/planner/*" access="hasAnyRole('ROLE_PERFORMER','ROLE_PLANNER')" /> -->
<!--        <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" /> -->
<!--        <access-denied-handler ref="oauthAccessDeniedHandler"  /> -->
<!--        <csrf disabled="true"/> -->
<!--    </http> -->

    <!-- others -->

    <beans:bean id="tokenStore"
        class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore" >
    </beans:bean>

    <beans:bean id="tokenConverter" class="org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter"/>

    <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:property name="refreshTokenValiditySeconds" value="100000" />
    </beans:bean>



    <beans:bean id="userApprovalHandler"
        class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler">
        <beans:property name="tokenStore" ref="tokenStore" />
        <beans:property name="requestFactory">
          <beans:bean class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
            <beans:constructor-arg ref="clientDetails" />
          </beans:bean>
        </beans:property>
    </beans:bean>

    <oauth2:authorization-server
        client-details-service-ref="clientDetails" token-services-ref="tokenServices"
        user-approval-handler-ref="userApprovalHandler">

        <oauth2:authorization-code />
        <oauth2:implicit />
        <oauth2:refresh-token />
        <oauth2:client-credentials />
        <oauth2:password authentication-manager-ref="clientAuthenticationManager"/>
    </oauth2:authorization-server>

    <beans:bean id="customUserAuthenticationProvider"
        class="com.eventapp.api.utilities.CustomAuthenticationProvider">
    </beans:bean>

    <beans:bean id="clientDetails"
        class="org.springframework.security.oauth2.provider.client.JdbcClientDetailsService">
        <beans:constructor-arg index="0">
            <beans:ref bean="dataSource" />
        </beans:constructor-arg>
        <beans:property name="selectClientDetailsSql" value="select client_id,client_secret,resource_ids,scope,authorized_grant_types,web_server_redirect_uri,authorities,access_token_validity,refresh_token_validity,additional_information,autoapprove from api_auth where client_id=?"></beans:property>
    </beans:bean>

    <bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased"
        xmlns="http://www.springframework.org/schema/beans">
        <constructor-arg>
            <list>
                <bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" />
                <bean class="org.springframework.security.access.vote.RoleVoter" />
                <bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
                <bean class="org.springframework.security.web.access.expression.WebExpressionVoter" />
            </list>
        </constructor-arg>
    </bean>
    <oauth2:resource-server id="resourceServerFilter"
        resource-id="test" token-services-ref="tokenServices" />
    <http pattern="/oauth/cache_approvals" security="none"
        xmlns="http://www.springframework.org/schema/security" />
    <http pattern="/oauth/uncache_approvals" security="none"
        xmlns="http://www.springframework.org/schema/security" />


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

    <beans:bean id="clientAuthenticationEntryPoint"
        class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
        <beans:property name="realmName" value="test/client" />
        <beans:property name="typeName" value="Basic" />
        <beans:property name="exceptionRenderer" ref="headerOnlyExceptionRender" />
    </beans:bean>

    <beans:bean id="oauthAccessDeniedHandler"
        class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" >
        <beans:property name="exceptionRenderer" ref="headerOnlyExceptionRender" />
        </beans:bean>

    <beans:bean id="headerOnlyExceptionRender" class="com.eventapp.api.utilities.OauthExceptionRenderer"/>


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


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

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



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

    <global-method-security
        pre-post-annotations="enabled" proxy-target-class="true">

        <expression-handler ref="oauthExpressionHandler" />
    </global-method-security>


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

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

</beans:beans>

Пользовательский файл аутентификации

package com.eventapp.api.utilities;

import java.util.Collection;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.eventapp.api.domain.ApiAuth;
import com.eventapp.api.model.UserModel;
import com.eventapp.api.repository.ApiAuthRepository;
import com.eventapp.api.service.AdminService;
import com.eventapp.api.service.PerformerService;
import com.eventapp.api.service.PlannerService;
import com.eventapp.commons.utilities.Crypto;

/**
 * CustomAuthenticationProvider class to provide Login authentication
 * 
 * @author Archit
 */
public class CustomAuthenticationProvider implements AuthenticationProvider {
 
    @Autowired
    private PerformerService performerService;
    
    @Autowired
    private PlannerService plannerService;
    
    @Autowired
    private AdminService adminService;
    
    @Autowired
    private ApiAuthRepository apiAuthRepository;
    
    @Override
    public Authentication authenticate(Authentication authentication) 
      throws AuthenticationException {
        
        
        String name = authentication.getName();
        
        String password = authentication.getCredentials().toString();
        
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        
        int type = Integer.parseInt(request.getParameter("type"));
        
        int isFacebookLogin = Integer.parseInt(request.getParameter("isFacebookLogin"));
        
        String clientId = request.getParameter("client_id");
        
        ApiAuth apiAuth = apiAuthRepository.findByClientId(clientId); 
        
        UserModel userModel = null;
        
        switch(type) {
            case 0:
                if(apiAuth.getAuthorities().equals("ROLE_PLANNER")) {
                    
                    userModel = plannerService.loadUserByUsername(name);
                
                } else {
                    throw new BadCredentialsException("Invalid Login Type");
                }
                
                break;
            case 1:
                if(apiAuth.getAuthorities().equals("ROLE_PERFORMER")) {
                    
                    userModel = performerService.loadUserByUsername(name);
                    
                } else {
                    
                    throw new BadCredentialsException("Invalid Login Type");
                }
                break;
                
            case 2:
                if(apiAuth.getAuthorities().equals("ROLE_ADMIN")) {
                    
                    userModel = adminService.adminService(name);
                    
                } else {
                    
                    throw new BadCredentialsException("Invalid Login Type");
                }   
                break;
                
            default:
                throw new BadCredentialsException("Invalid Login Type");
        }
        
        if (userModel == null || !userModel.getUsername().equalsIgnoreCase(name)) {
            
            throw new BadCredentialsException("Username not found");
        }
  
        if (isFacebookLogin == 0 && !password.equals(Crypto.decryptText(userModel.getPassword()))) {
        
            throw new BadCredentialsException("Invalid password");
            
        } 
        
        if(isFacebookLogin == 1 && !password.equals(Crypto.decryptText(userModel.getPassword()))) {
            
            throw new BadCredentialsException("Invalid password");
        }
        
        Collection<? extends GrantedAuthority> authorities = userModel.getAuthorities();
        
        return new UsernamePasswordAuthenticationToken(userModel.getId(), password, authorities);
    }
 
    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
}

Файл аутентификации

package com.eventapp.api.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity(name = "api_auth")
public class ApiAuth {

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE)
    private Integer id;
    
    @Column(name = "client_id")
    private String clientId;
    
    @Column(name = "resource_ids")
    private String resourceIds;
    
    @Column(name = "client_secret")
    private String clientSecret;
    
    @Column(name = "scope")
    private String scope;
    
    @Column(name = "authorized_grant_types")
    private String authorizedGrantTypes;
    
    @Column(name = "web_server_redirect_uri")
    private String webServerRedirectUri;
    
    @Column(name = "authorities")
    private String authorities;
    
    @Column(name = "access_token_validity")
    private Integer accessTokenValidity;
    
    @Column(name = "refresh_token_validity")
    private Integer refreshTokenValidity;
    
    @Column(name = "additional_information")
    private String additionalInformation;
    
    @Column(name = "autoapprove")
    private String autoApprove;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getClientId() {
        return clientId;
    }

    public void setClientId(String clientId) {
        this.clientId = clientId;
    }

    public String getResourceIds() {
        return resourceIds;
    }

    public void setResourceIds(String resourceIds) {
        this.resourceIds = resourceIds;
    }

    public String getClientSecret() {
        return clientSecret;
    }

    public void setClientSecret(String clientSecret) {
        this.clientSecret = clientSecret;
    }

    public String getScope() {
        return scope;
    }

    public void setScope(String scope) {
        this.scope = scope;
    }

    public String getAuthorizedGrantTypes() {
        return authorizedGrantTypes;
    }

    public void setAuthorizedGrantTypes(String authorizedGrantTypes) {
        this.authorizedGrantTypes = authorizedGrantTypes;
    }

    public String getWebServerRedirectUri() {
        return webServerRedirectUri;
    }

    public void setWebServerRedirectUri(String webServerRedirectUri) {
        this.webServerRedirectUri = webServerRedirectUri;
    }

    public String getAuthorities() {
        return authorities;
    }

    public void setAuthorities(String authorities) {
        this.authorities = authorities;
    }

    public Integer getAccessTokenValidity() {
        return accessTokenValidity;
    }

    public void setAccessTokenValidity(Integer accessTokenValidity) {
        this.accessTokenValidity = accessTokenValidity;
    }

    public Integer getRefreshTokenValidity() {
        return refreshTokenValidity;
    }

    public void setRefreshTokenValidity(Integer refreshTokenValidity) {
        this.refreshTokenValidity = refreshTokenValidity;
    }

    public String getAdditionalInformation() {
        return additionalInformation;
    }

    public void setAdditionalInformation(String additionalInformation) {
        this.additionalInformation = additionalInformation;
    }

    public String getAutoApprove() {
        return autoApprove;
    }

    public void setAutoApprove(String autoApprove) {
        this.autoApprove = autoApprove;
    }
}
 

Контроллер входа

@RequestMapping(method = RequestMethod.GET, value = "/login")
    
    public String get(
            @RequestHeader(value = "client_id", defaultValue = "Enter client id", required = true) final String clientId,
            @RequestHeader(value = "client_secret", defaultValue = "Enter client secret", required = true) final String clientSecret,
            @RequestHeader(value = "grant_type", defaultValue = "Enter Grant Type", required = true) final String grantType,
            @RequestHeader(value = "email", defaultValue = "Enter email", required = true) final String email,
            @RequestHeader(value = "password", defaultValue = "Password", required = true) final String password,
            @RequestHeader(value = "isFacebookLogin", defaultValue = "0", required = true) final Integer isFacebookLogin,
            @ApiParam(name = "type", value = "0 for Event Planner Login, 1 for Performer Login", required = true)
            @RequestParam(value = "type", defaultValue = "0", required = true) final Integer type)
            
                    throws Exception {
            if (clientId.equalsIgnoreCase("Enter client id") ||
                    clientSecret.equalsIgnoreCase("Enter client secret")) {
                throw new AccessDeniedException(ErrorInfo.EVENT_APP_ERROR_CODES.INVALID_API_CLIENT_SECRET.getApiStatusCode(),404);
            }
            
            
            String credentials = email+":"+password;
            
            String encodedCredentials = new String(Base64.encodeBase64(credentials.getBytes()));
            
            String url = getURL(grantType, clientId, clientSecret,type, isFacebookLogin);
            
            HttpHeaders headers = new HttpHeaders();
            
            headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
            headers.add("Authorization", "Basic " + encodedCredentials);
            HttpEntity<String> entity = new HttpEntity<String>(headers);

            ResponseEntity<String> responseEntity = null;
            
            try {
                
                responseEntity = restTemplate.exchange(url,HttpMethod.POST, entity, String.class);
                
            } catch (Exception exception) {
                throw new Exception();
            }
            String response = responseEntity.getBody();
        
            if (ApiErrorHandler.isError(responseEntity.getStatusCode())) {
                
                LoginErrorModel loginErrorModel = restSupport.readValueFromString(response, LoginErrorModel.class);
                
                if(loginErrorModel.getErrorMessage().equals("Invalid password")) {
                    throw new AccessDeniedException(ErrorInfo.EVENT_APP_ERROR_CODES.INVALID_PASSWORD.getApiStatusCode(),404);
                } else if(loginErrorModel.getErrorMessage().equals("Invalid User")) {
                    throw new AccessDeniedException(ErrorInfo.EVENT_APP_ERROR_CODES.INVALID_USER.getApiStatusCode(),404);
                } else if(loginErrorModel.getErrorMessage().equals("Bad client credentials")) {
                    throw new AccessDeniedException(ErrorInfo.EVENT_APP_ERROR_CODES.INVALID_API_CLIENT_SECRET.getApiStatusCode(),404);
                } else if(loginErrorModel.getError().equals("unsupported_grant_type")) {
                    throw new AccessDeniedException(ErrorInfo.EVENT_APP_ERROR_CODES.UNSUPPORTED_GRANT_TYPE.getApiStatusCode(),404);
                } else if(loginErrorModel.getErrorMessage().equals("Username not found")) {
                    throw new AccessDeniedException(ErrorInfo.EVENT_APP_ERROR_CODES.INVALID_USER.getApiStatusCode(),404);
                } else if(loginErrorModel.getErrorMessage().equals("Invalid Login Type")) {
                    throw new AccessDeniedException(ErrorInfo.EVENT_APP_ERROR_CODES.INVALID_LOGIN_TYPE.getApiStatusCode(),404);
                }
            }
            
            return response;
    }
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...