【问题标题】:Spring Security: separating controller by user roleSpring Security:按用户角色分离控制器
【发布时间】:2015-01-31 00:57:36
【问题描述】:

使用@RequestMapping,请求可以通过header或者request参数关联到不同的控制器函数。有没有办法根据用户用户角色来实现这一目标?目的是避免控制器中的 if 语句。

【问题讨论】:

标签: spring-mvc spring-security


【解决方案1】:

根据用户角色实现AuthenticationSuccessHandler onAuthenticationSuccess 重定向到特定控制器。

【讨论】:

  • 谢谢,虽然这适用于登录后的单个 url,但我正在寻找一种通用解决方案,可以应用于任何控制器,如 @RequestMapping (params="a=b")
【解决方案2】:

据我所知,没有任何开箱即用的功能,但如果您愿意,您可以创建自定义映射注释来为您执行此路由。

我实际上并没有尝试过任何代码,但类似:

你的新注解,类似@UserRoleMapping("ROLE_ADMIN")

@Target( ElementType.TYPE )
@Retention(RetentionPolicy.RUNTIME)
public @interface UserRoleMapping {
    String[] value();
}

接下来,您可以扩展标准 Spring RequestMappingHandlerMapping 类(这是处理 @RequestMapping 注释的标准映射的类)。您只需要告诉映射处理程序也考虑自定义条件:

public class UserRoleRequestCondition extends RequestMappingHandlerMapping {
    @Override protected RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {
        UserRoleMapping typeAnnotation = AnnotationUtils.findAnnotation(handlerType, UserRoleMapping.class);
        return (typeAnnotation != null) ? new UserRoleRequestCondition( typeAnnotation.value() ) : null;
    }
}

上面的代码只是检查控制器是否有你在上面创建的新注解,如果找到它会返回一个新的条件类,使用你在注解中设置的值构造(例如“ROLE_ADMIN”)。此 MappingHandler 需要在您的 Spring 配置中设置(无论您当前设置 RequestMappingHandlerMapping 的位置,只需将其替换为其中之一即可)。

接下来我们需要创建自定义条件 - 这是将根据请求调用以确定请求是否与控制器匹配的人:

public class UserRoleRequestCondition implements RequestCondition<UserRoleRequestCondition> {
    private final Set<String> roles;

    public UserRoleRequestCondition( String... roles ) {
        this( Arrays.asList(roles) );
    }

    public UserRoleRequestCondition( Collection<String> roles ) {
        this.roles = Collections.unmodifiableSet(new HashSet<String>(roles));
    }

    @Override public UserRoleRequestCondition combine(UserRoleRequestCondition other) {
        Set<String> allRoles = new LinkedHashSet<String>(this.roles);
        allRoles.addAll(other.roles);
        return new UserRoleRequestCondition(allRoles);
    }

    @Override public UserRoleRequestCondition getMatchingCondition( HttpServletRequest request ) {
        UserRoleRequestCondition condition = null;
        for (String r : roles){
            if ( request.isUserInRole( r ) ){
                condition = this;
            }
        }
        return condition;
    }

    @Override public int compareTo(UserRoleRequestCondition other, HttpServletRequest request) {
        return (other.roles - this.roles).size();
    }
}

在上面,方法getMatchingCondition是我们匹配请求的地方。 (抱歉,如果我遗漏了一些分号或返回关键字等 - 这是基于 groovy,但希望如果你在 java 中,你可以找出这些位的去向!)

向 Marek 提供更详细的答案,让他更详细地回答了基于子域的自定义路由的更完整的解决方案,当我必须实现类似的东西时,我使用了该解决方案! How to implement @RequestMapping custom properties - 这提供了有关正在发生的事情的更多详细信息,以及如何拥有方法级别的注释(本示例跳过了这一点,只定义了类级别的注释)

我也在这里写了一些笔记:http://automateddeveloper.blogspot.co.uk/2014/12/spring-mvc-custom-routing-conditions.html

【讨论】:

  • 谢谢,这正是我要找的。​​span>
猜你喜欢
  • 1970-01-01
  • 2011-07-21
  • 2014-12-26
  • 1970-01-01
  • 1970-01-01
  • 2013-08-26
  • 2015-05-19
  • 2016-10-14
  • 1970-01-01
相关资源
最近更新 更多