在 Spring 中,如何根据 UserDetails 对象中的 属性 阻止对路径的访问?

In Spring, how can I block access to a path based on a property in my UserDetails object?

我正在使用 Spring 3.2.11.RELEASE、Spring Security 3.1.4.RELEASE,但如果可以解决我的问题,可以升级 Spring 安全模块问题。在我的 UserDetails 对象中,我有以下 属性 …

public class MyAuthenticationUser implements UserDetails, CredentialsContainer
{
    …
    public boolean isSampleUser()
    {
        return isSampleUser;
    }   // isSampleUser

然后我有一个控制器,看起来像

@Controller
@RequestMapping("/basedir")
public class basedirController
{

    @RequestMapping(value = “/page1”, method = RequestMethod.GET)
    public ModelAndView doGetPDResources(final Model model,
                                         final Principal principal) throws IOException
    {
    …
    }


    @RequestMapping(value = “/page2”, method = RequestMethod.GET)
    public ModelAndView doGetPDCenter(final Model model, final HttpServletRequest request) throws IOException
    {
        return new ModelAndView("basedir/pdcenter");
    }

…

如果我的 UserDetails 对象的“isSampleUser”属性 的计算结果为真的?我是否必须将逻辑硬编码到我的控制器的每个方法中以检查此 属性(似乎有一种更巧妙的方法来解决这个问题)?

正如其他人所建议的那样,您似乎应该能够使用角色来做到这一点。

例如,如果 isSampleUser 为真,您可以确保 ROLE_SAMPLE 是角色的一部分。假设有问题的另一个角色是 ROLE_USER,那么您可以添加以下规则:

<http ... use-expressions="true">
    ...
    <intercept-url pattern="/base-dir/**" 
                   access="hasRole('ROLE_USER') and !hasRole('ROLE_SAMPLE')"/> 
    ...
</http>

如果您使用的是 Java 配置,那么它看起来像:

http
    .authorizeRequests()
        ...
        .antMathers("/base-dir/**").access("hasRole('ROLE_USER') and !hasRole('ROLE_SAMPLE')")
        ...

如果你真的不想添加其他角色,你可以这样做:

<http ... use-expressions="true">
    ...
    <intercept-url pattern="/base-dir/**" 
                   access="principal.sampleUser ? denyAll : hasRole('ROLE_USER')"/> 
    ...
</http>

这说明对于以 /base-dir/** 开头的 URL 如果 sampleUser returns 为真,则拒绝访问,否则需要 ROLE_USER