Spring Security:按用户角色分离控制器

时间:2014-12-02 17:16:24

标签: spring-mvc spring-security

使用@RequestMapping,请求可以通过标头或请求参数与不同的控制器功能相关联。有没有办法在用户用户角色上实现这个基础?目的是避免在控制器中使用if语句。

2 个答案:

答案 0 :(得分:1)

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

我实际上没有尝试过这些代码,但是类似于:

您的新通知,使用方式@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”)构造。需要在Spring配置中设置此MappingHandler(无论您当前设置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

答案 1 :(得分:0)

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