答案是:
不会。去掉用户的权限后,该用户仍然可以执行相关的操作,即使系统管理员 “刷新了缓存”
被去掉权限的用户只有在更新自己的信息、或者退出重新登录以后,才能发现自己失去了指定的权限。
==================================================
分析:
收集到的事实:
1.去掉用户的某权限(即角色,role)后,该用户查看自己的资料,会发现该角色的确被去掉了,但经过代码跟踪,我发现,该用户对应的Authentication对象中,本来该去掉的authrotiy还在!
2.用户在登录后,后续的操作不会被 AbstractUserDetailsAuthenticationProvider 拦截。也就是说,用户的Authentication对象不会被更新。相反,这个对象是从SerurityContext中直接取出来的老对象,见 AbstractSecurityInterceptor
authenticated = SecurityContextHolder.getContext().getAuthentication()
确认原因:
User对象在数据库中被修改后,虽然它在的内存中的对象会被更新(UserSerurityAdvice类中会显式地刷新UserCache),但其对应的Authentication对象却不会被更新。
=============================================
解决办法:
1.
配置 filterInvocationInterceptor 的 alwaysReauthenticate属性为true,也就是说用户每进行一次操作,都要去搜集一下它的角色。正如acegi文档所说:
It (指
AbstractSecurityInterceptor) also has configurable settings to indicate whether an Authentication object should be re-authenticated on each secure object invocation.
By default it just accepts any Authentication inside the SecurityContextHolder is authenticated if Authentication.isAuthenticated() returns true. This is great for performance, but not ideal if you want to ensure up-to-the-moment authentication validity.
For such cases you’ll probably want to set the AbstractSecurityInterceptor.alwaysReauthenticate property to true.
问题是解决了。但文档里也说,如果每次都去搜集一下用户的角色,由于牵涉到数据库查询,可能会在性能上有比较大的消耗。但在Appfuse中,我们不必为此担忧,因为我们并不需要每次都去数据库中查询用户的角色,Appfuse的 userCache 会帮我们缓存用户的信息,并且可以保证缓存中的信息永远与数据库中一致。