При миграции возникает много проблем, раньше я использовал 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;
}