У меня проблемы со съемкой конфигурации безопасности с весенней загрузкой, которая когда-то работала, но теперь не распознает мои пользовательские определения. Моя цель состояла в том, чтобы защитить все наши Сервисы с помощью безопасности уровня метода в Spring с помощью пользовательских аннотаций.
Когда я запускаю сервис, создается экземпляр моего CustomMethodSecurityConfig, и он вызывает createExpressionHandler (), но когда я делаю запрос к сервисуон не вызывает createSecurityExpressionRoot (...) для моего CustomMethodSecurityExpressionHandler, но для DefaultWebSecurityExpressionHandler.
Я ценю любые идеи, которые кто-либо может предоставить, почему Spring Security не распознает мои выражения, определенные в моем CustomMethodSecurityExpression.
Вот фрагмент моего класса GlobalMethodSecurityConfiguration
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class CustomMethodSecurityConfig extends GlobalMethodSecurityConfiguration {
private final MyService1 myService1;
private final MyService2 myService2;
private final MyService3 myService3;
@Autowired
public CustomMethodSecurityConfig(MyService1 myService1, MyService2 myService2,
MyService3 myService3) {
this.myService1 = myService1;
this.myService2 = myService2;
this.myService3 = myService3;
}
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
CustomMethodSecurityExpressionHandler expressionHandler =
new CustomMethodSecurityExpressionHandler(myService1, myService2, myService3);
expressionHandler.setPermissionEvaluator(permissionEvaluator());
return expressionHandler;
}
}
Вот фрагмент моего класса DefaultMethodSecurityExpressionHandler
public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {
private final MyService1 myService1;
private final MyService2 myService2;
private final MyService3 myService3;
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
public CustomMethodSecurityExpressionHandler(MyService1 myService1, MyService2 myService2,
MyService3 myService3) {
this.myService1 = myService1;
this.myService2 = myService2;
this.myService3 = myService3;
}
@Override
protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication,
MethodInvocation invocation) {
CustomMethodSecurityExpressionRoot root = new CustomMethodSecurityExpressionRoot(authentication,
myService1,
myService2,
myService3);
root.setPermissionEvaluator(getPermissionEvaluator());
root.setTrustResolver(this.trustResolver);
root.setRoleHierarchy(getRoleHierarchy());
return root;
}
}
Вот фрагмент моего SecurityExpressionRoot, этогде я определяю свои выражения SpEL, которые я использую в аннотациях к моим Сервисам. Я включил только упрощенный, isUser в качестве примера. То, что делают эти методы, не важно, но тот факт, что они видимы.
public class CustomMethodSecurityExpressionRoot extends SecurityExpressionRoot
implements MethodSecurityExpressionOperations {
private Object filterObject;
private Object returnObject;
private MyService1 myService1;
private MyService2 myService2;
private MyService3 myService3;
public CustomMethodSecurityExpressionRoot(
Authentication authentication,
MyService1 myService1,
MyService2 myService2,
MyService3 myService3) {
super(authentication);
this.myService1 = myService1;
this.myService2 = myService2;
this.myService3 = myService3;
}
@Override
public Object getFilterObject() {
return this.filterObject;
}
@Override
public Object getReturnObject() {
return this.returnObject;
}
@Override
public void setFilterObject(Object obj) {
this.filterObject = obj;
}
@Override
public void setReturnObject(Object obj) {
this.returnObject = obj;
}
@Override
public Object getThis() {
return this;
}
//All custom SpEL methods
public boolean isUser(Long userId) {
SecurityUser user = (SecurityUser) this.getPrincipal();
return user.getUserId() == userId;
}
...
}
И, наконец, вот фрагмент моего WebSecurityConfigurerAdapter, который используется в тандеме, он проверяет маркер внешней аутентификации от нашего UAAserver.
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
prePostEnabled = true,
proxyTargetClass = true)
public class ServiceSecurityConfig extends WebSecurityConfigurerAdapter {
private final TokenCheckService _tokenCheckService;
@Autowired
ServiceSecurityConfig(TokenCheckService tokenCheckService) {
_tokenCheckService = tokenCheckService;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(new TokenAuthenticationProvider(_tokenCheckService));
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/api/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.anonymous()
.disable()
.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(new UnAuthorizedEntryPoint())
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.anyRequest().authenticated();
http.addFilterBefore(new AuthenticationTokenFilter(), BasicAuthenticationFilter.class);
}
}
Редактировать: Кажется, я думаю, что это проблема с моими WebDecisionVoters, перезаписываемыми во время инициализации. Если у меня есть точка останова в конструкторе «Утверждение»
AffirmativeBased(List<AccessDecisionVoter<? extends Object>> decisionVoters)
, я вижу, как для AffirrativeBased создаются три участника голосования, одним из которых является PreInvocationAuthorizationAdviceVoter, который содержит ссылку на мой обработчик выражений. Я полагаю, что это создается созданием компонента bean метода methodSecurityInterceptor.
Когда я продолжаю точку останова, я снова обращаюсь к тому же конструктору, основанному на утверждениях, но только с одним избирателем принятия решения, WebExperssionVoter со ссылкой на экземпляр DefaultWebSecurityExpressionHandler. ,Я полагаю, что это создается созданием bean-компонента springSecurityFilterChain.