繁体   English   中英

在 Spring 引导中为当前登录的用户创建 RESTful web 服务

[英]Create RESTful web service for current logged user in Spring Boot

我有 URL 用于用户仪表板(/users/{userId})。

我想为当前登录的用户支持 /users/current,我搜索了实现该功能的方法,并通过以下代码做到了这一点。

但是,我认为这太过分了,我想知道是否有更好/更简单的方法来做到这一点。

@Controller
@RequestMapping("/users/{target}")
public class UserController {

    @GetMapping
    public String get(@PathVariable User target) {
        return "dashboard";
    }

    @PostMapping
    public String put(@PathVariable User target, ...) {
        ...
    }

    @GetMapping("licenses")
    public String getLicenses(@PathVariable User target, ...) {
        ...
    }

    ...
}

@Configuration
@RequiredArgsConstructor
public class MethodHandlersConfig {

    private final RequestMappingHandlerAdapter adapter;

    @PostConstruct
    public void prioritizeCustomArgumentMethodHandlers() {
        List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<>(adapter.getArgumentResolvers());
        List<HandlerMethodArgumentResolver> customResolvers = adapter.getCustomArgumentResolvers();
        argumentResolvers.removeAll(customResolvers);
        argumentResolvers.addAll(0, customResolvers);
        adapter.setArgumentResolvers(argumentResolvers);
    }
}

@Component
@RequiredArgsConstructor
public class UserResolver extends PathVariableMethodArgumentResolver {

    private final UserService userService;

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return User.class.isAssignableFrom(parameter.getParameterType());
    }

    @Override
    @SuppressWarnings("rawtypes")
    protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
        User user;
        HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);
        Map path = (Map) servletRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
        String target = (String) path.get(name);
        if (target.equals("current")) {
            Authentication auth = SecurityContextHolder.getContext().getAuthentication();
            if (auth == null) {
                throw new InsufficientAuthenticationException("User is not authenticated");
            }
            user = (User) auth.getPrincipal();
        } else {
            user = userService.loadUserByUsername(target);
        }
        request.setAttribute("username", target, RequestAttributes.SCOPE_REQUEST);
        request.setAttribute("user", user, RequestAttributes.SCOPE_REQUEST);
        return user;
    }
}

PS我想我用自定义注释(@UserPath)做了一个更好的解决方案


@Component
@RequiredArgsConstructor
public class UserResolver extends AbstractNamedValueMethodArgumentResolver implements UriComponentsContributor {

    private final UserService userService;

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(UserPath.class);
    }

    @Override
    protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) {
        UserPath annotation = parameter.getParameterAnnotation(UserPath.class);
        return new NamedValueInfo(annotation.name(), true, ValueConstants.DEFAULT_NONE);
    }

    @SuppressWarnings("unchecked")
    protected String getValue(String name, WebRequest request) {
        Map<String, String> vars = (Map<String, String>) request.getAttribute(
                HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
        return vars.get(name);
    }

    @Override
    @Nullable
    protected User resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
        UserPath annotation = parameter.getParameterAnnotation(UserPath.class);

        String userObj = getValue(name, request);
        User current = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (userObj.equals("current")) {
            return current;
        } else {
            User found = userService.loadUserByUsername(userObj);
            if (annotation.admin() &&
                    !current.getId().equals(found.getId()) &&
                    !current.getAuthorities().contains(UserAuthority.ROLE_ADMIN)) {
                throw new InsufficientAuthenticationException("Admin permission is required");
            }
            return found;
        }
    }

    @Override
    protected void handleResolvedValue(Object arg, String name, MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) {
        User user = (User) arg;
        String userObj = getValue(name, webRequest);
        mavContainer.addAttribute("user", user);
        mavContainer.addAttribute("username", userObj);
    }

    @Override
    public void contributeMethodArgument(MethodParameter parameter, Object value,
                                         UriComponentsBuilder builder, Map<String, Object> uriVariables, ConversionService conversionService) {
        uriVariables.put(parameter.getParameterAnnotation(UserPath.class).value(), value.toString());
    }
}

也许带有 AbstractNamedValueMethodArgumentResolver 的自定义注释将是最好的解决方案。 阅读问题的 PS 以获取更多详细信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM