2016-08-30 106 views
1

我想了解spring安全性。我正在使用java-config而不是xml。我试图创建一个控制器,然后测试@PreAuthorize表示法。但在我的给定代码中,@PreAuthorize仅在与getActiveSessions函数一起使用时才有效,但在与getName函数一起使用时它不起作用。所以这段代码按预期工作@PreAuthorize不起作用从另一个函数调用的函数

public class DemoSessionController extends SessionController{ 

     @RequestMapping("/welcome/{a}") 
     @PreAuthorize("hasRole('ROLE_ADMIN')") 
     public String getActiveSessions(@PathVariable String a) { 
      // TODO Auto-generated method stub 
      String str = getName(a); 
      return str; 
     } 

     public String getName(String name) { 
      // TODO Auto-generated method stub 
      return "This is "+name+""; 
     } 
    } 

但这并不

public class DemoSessionController extends SessionController{ 

    @RequestMapping("/welcome/{a}") 
    public String getActiveSessions(@PathVariable String a) { 
     // TODO Auto-generated method stub 
     String str = getName(a); 
     return str; 
    } 

    @PreAuthorize("hasRole('ROLE_ADMIN')") 
    public String getName(String name) { 
     // TODO Auto-generated method stub 
     return "This is "+name+""; 
    } 
} 

有人能解释为什么第二种情况下不工作,我怎样才能使它发挥作用?谢谢 !!

+2

Spring使用代理申请AOP。当只使用代理方法调用INTO时,对象会通过代理,内部方法调用绕过代理。为了使它工作,您需要一个完整的AOP解决方案,比如AspectJ,可以加载或编译时间编码。 –

+0

@ M.Deinum感谢您的及时和明确的答复。我明白为什么现在不行。关于使它工作,你说'全面爆炸'的方式,这是否意味着解决方案会很麻烦?你能否给任何可能有帮助的资源提供链接?谢谢 !! – varunkr

+0

我知道它与Java配置一起工作,但我现在无法访问我的代码。基本上,有两个上下文(DispatcherServlet vs其他)。如果安全配置适用于正确的(或两者)上下文,注释才会起作用。搜索网络,你会找到解决方案。一旦配置正确,它将工作。 – Codo

回答

1

正如在评论中提到的,只有在从外部调用对象时才会处理注释。有几个解决方案。

您可以拆分需要注释以在单独对象中处理的方法,例如,一个管理对象,其注释为

@PreAuthorize("hasRole('ROLE_ADMIN')") 

在类级别上。这样你就不需要注释每种方法。您应该将该类中的内部方法标记为private,以防止它们从外部使用。这需要对应用程序逻辑进行重新排序,但将所有管理任务放在一个对象中可能会有所帮助。

另一种解决方案显然是为一个方法执行的所有任务添加所需的注释,包括由公共方法使用的方法执行的注解。

编辑1:

新增样本的类,使提出的解决方案更清晰

public class UserSessionController extends SessionController{ 
@Inject 
private AdminFacade adminFacade; 

@RequestMapping("/welcome/{a}") 
public String getActiveSessions(@PathVariable String a) { 
    return adminFacade.getName(a); 
} 
} 

@PreAuthorize("hasRole('ROLE_ADMIN')") 
public class AdminFacade { 

public String getName(String name) { 
    return "This is "+name; 
} 
public String getDetailsForAdmin(String param) { 
    return "admin details"; 
} 
} 
+0

感谢您的回复!但我无法理解你。你可以添加一些代码来解释第一种方法吗?这种方法等同于说我需要在其他bean中使用getName()方法吗?谢谢 !! – varunkr

+0

嘿,非常感谢编辑。你的建议确实有效。我确实尝试过类似的方法,但它并没有提前工作。原因是我正在做类似的事情,返回新的AdminFacade()。getName(a),但这没有奏效。在你的情况下,你正在注入尚未初始化的AdminFacade对象。其实我有两个疑问。 1.)为什么你的方法工作,我的不是。 2)为什么没有adminFacade.getName(a)产生一个空指针,因为我看不到它是如何被初始化的?请清除我的疑问,我会接受你的回答!谢谢 !! – varunkr

+0

cdi容器(在你的情况下为spring)将创建一个AdminFacade对象,并在它看到@Inject时将其设置为变量。手动创建对象将不起作用,因为当调用对象上的方法时,cdi容器无法做到“神奇”,即处理其他注释。我建议你看看CDI教程http://docs.oracle.com/javaee/6/tutorial/doc/giwhl.html如果你想知道更多的细节。 – Guenther

相关问题