All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.security.web.method.annotation.UserDetailsArgumentResolver Maven / Gradle / Ivy

package org.springframework.security.web.method.annotation;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.expression.BeanResolver;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

/**
 * @see org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver
 */
public class UserDetailsArgumentResolver implements HandlerMethodArgumentResolver {
  private ExpressionParser parser = new SpelExpressionParser();
  private BeanResolver beanResolver;
  private final UserDetailsService userDetailsService;

  public UserDetailsArgumentResolver(UserDetailsService userDetailsService) {
    this.userDetailsService = userDetailsService;
  }

  @Override
  public boolean supportsParameter(MethodParameter parameter) {
    return findMethodAnnotation(AuthenticationPrincipal.class, parameter) != null;
  }

  @Override
  public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
    Authentication authentication = orElseThrow(SecurityContextHolder.getContext().getAuthentication());

    if (authentication instanceof AnonymousAuthenticationToken || !authentication.isAuthenticated()) {
      throw new AccessDeniedException("Access is denied from... " + authentication.getPrincipal());
    }

    Object principal = authentication.getPrincipal();

    AuthenticationPrincipal authPrincipal = findMethodAnnotation(AuthenticationPrincipal.class, parameter);

    String expressionToParse = authPrincipal.expression();
    if (StringUtils.hasLength(expressionToParse)) {
      StandardEvaluationContext context = new StandardEvaluationContext();
      context.setRootObject(principal);
      context.setVariable("this", principal);
      context.setBeanResolver(beanResolver);

      Expression expression = this.parser.parseExpression(expressionToParse);
      principal = expression.getValue(context);
    }
    if (principal != null && !parameter.getParameterType().isAssignableFrom(principal.getClass())) {
      if (principal instanceof UserDetails && UserDetails.class.isAssignableFrom(parameter.getParameterType())) {
        try {
          UserDetails userDetails = this.userDetailsService.loadUserByUsername(authentication.getName());

          Field field = ReflectionUtils.findField(authentication.getClass(), "principal");
          Assert.notNull(field, "Not Found Field 'pricipal' from... " + authentication.getClass());
          ReflectionUtils.makeAccessible(field);
          ReflectionUtils.setField(field, authentication, userDetails);
          SecurityContextHolder.getContext().setAuthentication(authentication);
          return userDetails;
        }
        catch (UsernameNotFoundException e) {
          throw new AccessDeniedException(principal + " is not assignable to " + parameter.getParameterType(), e);
        }
      }
      throw new AccessDeniedException(principal + " is not assignable to " + parameter.getParameterType());
    }
    return orElseThrow(principal);
  }

  private  T orElseThrow(T t) {
    if (t == null) {
      throw new AccessDeniedException("Access is denied");
    }
    return t;
  }

  public void setBeanResolver(BeanResolver beanResolver) {
    this.beanResolver = beanResolver;
  }

  private  T findMethodAnnotation(Class annotationClass, MethodParameter parameter) {
    T annotation = parameter.getParameterAnnotation(annotationClass);
    if (annotation != null) {
      return annotation;
    }
    Annotation[] annotationsToSearch = parameter.getParameterAnnotations();
    for (Annotation toSearch : annotationsToSearch) {
      annotation = AnnotationUtils.findAnnotation(toSearch.annotationType(), annotationClass);
      if (annotation != null) {
        return annotation;
      }
    }
    return null;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy