'잘못된 빈 정의'EvaluationContextExtensionSupport 및 사용자 정의와 2.1.0에 봄 부팅 2.0.6 마이그레이션 PermissionEvaluator

Broek 덴 Sebastiaan 반 :

봄에서 부팅 2.1.0는 EvaluationContextExtensionSupport사용되지 않으며 https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/repository/query/spi/EvaluationContextExtensionSupport.html는 말한다 EvaluationContextExtension 구현 직접

이 단지되지 않습니다하더라도, 그것은 바로이 스택 트레이스이 업그레이드에 실패 시작 :

Caused by: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'methodSecurityInterceptor' defined in class path resource [org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.class]: Cannot register bean definition [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration; factoryMethodName=methodSecurityInterceptor; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.class]] for bean 'methodSecurityInterceptor': There is already [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=methodSecurityConfiguration; factoryMethodName=methodSecurityInterceptor; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [ournamespace/configuration/MethodSecurityConfiguration.class]] bound.
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.registerBeanDefinition(DefaultListableBeanFactory.java:894)
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod(ConfigurationClassBeanDefinitionReader.java:274)
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:141)
...and so on

나는이 추측하고있어 우리가 우리의 현재 코드에서 무슨 일을하는지 단지 부작용 그래서 명시 적으로,이 콩을 대체하지 않습니다. 내가 허용 할 경우 콩과 오버라이드 (override) spring.main.allow-bean-definition-overriding=true에 따라 https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.1-Release-Notes#bean-overriding 나는 단순히 다른 예외를 얻을.

java.lang.IllegalStateException: Duplicate key org.springframework.data.spel.ExtensionAwareEvaluationContextProvider$EvaluationContextExtensionAdapter@10dfbbbb at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133) ~[na:1.8.0_162]

그러나, 나는 심지어 어떤 콩 동작을 재정의하고 싶지 않아, 목표는 다시 봄이 작업에하고자하는 방법을 작동하는 사용자 지정 권한 평가를 얻는 것입니다.

이 마지막 버전에서 작업을했던 방법입니다 :

봄 부팅 2.0.6에서 우리는 일에 우리의 사용자 정의 PermissionEvaluator 클래스를 얻기 위해 다음과 같은했다 :

확장하는 클래스 EvaluationContextExtensionSupport

import org.springframework.data.repository.query.spi.EvaluationContextExtensionSupport;
import org.springframework.security.access.expression.SecurityExpressionRoot;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;

public class SecurityEvaluationContextExtension extends EvaluationContextExtensionSupport {

    @Override
    public String getExtensionId() {
        return "security";
    }

    @Override
    public SecurityExpressionRoot getRootObject() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            return new SecurityExpressionRoot(authentication) {
        };
    }
}

그리고 식 핸들러가 우리의 권한 평가자로 생성하고있는 @Bean과 함께하는 클래스 EvaluationContextExtension

import ournamespace.security.CustomPermissionEvaluator;
import ournamespace.security.SecurityEvaluationContextExtension;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.repository.query.spi.EvaluationContextExtension;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;

@Configuration
@RequiredArgsConstructor
public class MethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {

    private final CustomPermissionEvaluator permissionEvaluator;

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        DefaultMethodSecurityExpressionHandler expressionHandler =
                new DefaultMethodSecurityExpressionHandler();
        expressionHandler.setPermissionEvaluator(permissionEvaluator);
        return expressionHandler;
    }

    @Bean
    EvaluationContextExtension securityExtension() {
        return new SecurityEvaluationContextExtension();
    }
}

그리고 마지막으로 우리는 다른 대부분 빈 클래스에서이 있습니다 :

@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
   ...
}

우리는 단지에 넣고 경우 사용자 지정 권한 평가자는 모든 메소드에 적용되지 않은 적이 있기 때문입니다 MethodSecurityConfiguration클래스입니다. 우리는의 다른없는 구성 아무것도 할 수 있도록 문제의 서버는 OAuth2를 리소스 서버입니다 WebSecurityConfigurerAdapter. 우리는 또한 우리 자신을 구현 UserDetails하고 우리는 확장 DefaultUserAuthenticationConverter이 어떤 식 으로든 새로운 솔루션 관련이있는 경우.

내가 구현하는 시도 EvaluationContextExtension사용 중단 경고에 명시된 바와 같이, 직접 클래스를. 그것은가 인터페이스를 확장 변경하여 단순한 수정입니다 implements EvaluationContextExtension. 나는 또한 겉으로는 새로운 패키지로 변경 시도org.springframework.data.spel.spi

나는 우리 자신의 삭제 시도했습니다 SecurityEvaluationContextExtension및 반환 https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/data/repository/query/SecurityEvaluationContextExtension.html을 직접 콩으로 하지만 어떤 이유로 데이터 패키지는 봄 부팅 2.1.0에서 사용할 수 없음

난 그냥 아예 그 빈의 정의를 제거하려고했습니다.

이 모든 일들이 시작시 다양한 '잘못된 빈 정의'오류가 발생.

마이그레이션 설명서 나이 지금 일에 가정 방법에 대한 다른 자원을 어디서 찾을 수 있는지 아는 사람 있나요?

그냥 참조를 위해서, 실제 CustomPermissionEvaluator클래스 :

import ournamespace.configuration.Constants;
import ournamespace.exception.InternalException;
import ournamespace.model.Account;
import ournamespace.model.Member;
import ournamespace.model.Project;
import ournamespace.repository.MemberRepository;
import ournamespace.service.ServiceUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

import java.io.Serializable;

import static ournamespace.model.MemberStatus.JOINED;
import static ournamespace.model.ProjectRole.*;

@RequiredArgsConstructor
@Component
public class CustomPermissionEvaluator implements PermissionEvaluator {

    private final MemberRepository memberRepository;

    @Override
    public boolean hasPermission(Authentication auth, Object targetDomainObject, Object permission) {
        if (targetDomainObject == null)
            return false;

        if (!(permission instanceof String))
            return false;

        if (auth == null)
            return false;

        Account account = ServiceUtil.getAccount(auth);

        if (targetDomainObject instanceof Project)
            return hasPermissionOnProject(account, (Project) targetDomainObject, (String) permission);
        //and so on
    }
}

그리고 그것은 사용의 방법에 대한 예 :

public interface ProjectRepository extends PagingAndSortingRepository<Project, UUID> {

    @Override
    @PreAuthorize("hasPermission(#project, " + Constants.WRITE + ")")
    <S extends Project> S save(@Param("project") S project);
}
jzheaux :

난 당신의 코드를 가져다가 그것에서 샘플 응용 프로그램을 만들었습니다. 난 여기를 게시 :

https://github.com/jzheaux/stackoverflow-53410526

귀하의 @EnableGlobalMethodSecurity주석이 켜져 있습니다 WebSecurityConfigurerAdapter. 또한 확장하는 클래스를 가지고 GlobalMethodSecurityConfiguration. 이것은 당신이보고있는 =>이 개 무엇을 할 수있는, 시간에 시작할 때 어떤 순서 문제가 발생할 수 MethodSecurityExpressionHandler의가 생성뿐만 아니라이 개 얻을 EvaluationContextExtension들.

이것이 바로 내가 당신과 일치하는 경우 또는하지 (나는 그것이 같은데요), 여부 @EnableGlobalMethodSecurity사용자 정의로 GlobalMethodSecurityConfiguration, 일이 잘을 시작했다.

또한,하지만, 당신의 정의는 것 같다 EvaluationContextExtension봄 보안 기본과 매우 유사합니다. 할 수 있다면 봄 부팅을 노출하기 때문에 당신이 때 자동으로 해당 클래스뿐만 아니라 해당 빈 메소드를 제거하는 것이 좋습니다 spring-boot-starter-securityspring-security-data종속있다.

추천

출처http://43.154.161.224:23101/article/api/json?id=137885&siteId=1