webapi authorizee 可以判断角色吗

用手机扫描以上二维码直接访问此文。
Acegi+hibernate 动态实现基于角色的权限管理
最近在做项目遇到了权限管理,用户要求可以自己建立不同的角色对系统的资源进行控制, 不同的用户有不同的角色,又恰恰框架中用到了struts+spring+hibernate,要求在web层调用 业务逻辑层 时不考虑权限,web层可以控制用户的显示界面,逻辑层处理用户权限问题。
想来想去好像只有spring 的aop 可以做到,在调用到 接口 中的方法时,首先检查用户的权限,如果检查通过则继续执行,否则抛出异常。但是新的问题又出现了,如何在逻辑层上来得到当前用户的id,以致用户的 角色,总不能每次都要从web中传来一个 httprequest,或者 session 这类的吧。在网上看了很多资料,发现了acegi,恰好解决了以上的难题,具体的实现原理这里就不多说了,网上有很多相关资料。
说正题,首先来看看acegi 的官方 example ,我下载的是acegi-security-1.0.0-RC1,解压缩后可以看到acegi-security-sample-contacts-filter.war,打开配置文件有这样几句
&bean id=&contactManagerSecurity& class=&org. acegisecurity. intercept. method. aopalliance. MethodSecurityInterceptor&&
&property name=&authenticationManager&&&ref bean=&authenticationManager&/&&/property&
&property name=&accessDecisionManager&&&ref local=&businessAccessDecisionManager&/&&/property&
&property name=&afterInvocationManager&&&ref local=&afterInvocationManager&/&&/property&
&property name=&objectDefinitionSource&&
sample. contact. ContactManager. create=ROLE_USER
sample. contact. ContactManager. getAllRecipients=ROLE_USER
sample. contact. ContactManager. getAll=ROLE_USER,AFTER_ACL_COLLECTION_READ
sample. contact. ContactManager. getById=ROLE_USER,AFTER_ACL_READ
sample. contact. ContactManager. delete=ACL_CONTACT_DELETE
sample. contact. ContactManager. deletePermission=ACL_CONTACT_ADMIN
sample. contact. ContactManager. addPermission=ACL_CONTACT_ADMIN
&/property&
可以看到它是通过读配置文件来判断执行某个方法所需要的角色的,再看这几句
&bean id=&filterInvocationInterceptor& class=&org. acegisecurity. intercept. web. FilterSecurityInterceptor&&
&property name=&authenticationManager&&&ref bean=&authenticationManager&/&&/property&
&property name=&accessDecisionManager&&&ref local=&httpRequestAccessDecisionManager&/&&/property&
&property name=&objectDefinitionSource&&
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/index. jsp=ROLE_ANONYMOUS,ROLE_USER
/hello. htm=ROLE_ANONYMOUS,ROLE_USER
/logoff. jsp=ROLE_ANONYMOUS,ROLE_USER
/switchuser. jsp=ROLE_SUPERVISOR
/j_acegi_switch_user=ROLE_SUPERVISOR
/acegilogin. jsp*=ROLE_ANONYMOUS,ROLE_USER
/**=ROLE_USER
&/property&
同样是将页面的访问权限写死在配置文件中,再来看看它的tag是如何处理的
&auth:authorize ifAnyGranted=&ROLE_DELETE&&
&a href=&&&删除&/a&
&/auth:authorize&
可见它是要求我们对链接或者其他资源的保护时提供 用户角色,可是既然角色是用户自己添加的我们又如何来写死在这里呢?
还有就是它对用户验证默认使用的是jdbc,即 JdbcDaoImpl
&bean id=&transactionManager& class=&org. springframework. jdbc. datasource. DataSourceTransactionManager&&
&property name=&dataSource&&&ref local=&dataSource&/&&/property&
而我们希望基于Hibernate的Dao来实现。
可见仅仅使用现有的acegi 是 无法满足我们项目开发的需求的。
1: 开发基于数据库的保护资源。
看过acegi的源代码就会知道,对保护资源的定义是通过实现ObjectDefinitionSource这个接口来实现的,而且acegi为我们提供了默认实现的抽象类
public abstract class AbstractMethodDefinitionSource
implements MethodDefinitionSource {
//~ Static fields/initializers =============================================
private static final Log logger = LogFactory. getLog (AbstractMethodDefinitionSource. class );
//~ Methods ================================================================
public ConfigAttributeDefinition getAttributes ( Object object )
throws IllegalArgumentException {
Assert. notNull (object, & Object cannot be null& );
if (object instanceof MethodInvocation ) {
return this. lookupAttributes ( ( (MethodInvocation ) object ). getMethod ( ) );
if (object instanceof JoinPoint ) {
JoinPoint jp = (JoinPoint )
Class targetClazz = jp. getTarget ( ). getClass ( );
String targetMethodName = jp. getStaticPart ( ). getSignature ( ). getName ( );
Class [ ] types = ( (CodeSignature ) jp. getStaticPart ( ). getSignature ( ) )
. getParameterTypes ( );
if (logger. isDebugEnabled ( ) ) {
logger. debug (&Target Class: & + targetClazz );
logger. debug (&Target Method Name: & + targetMethodName );
for ( int i = 0; i & types. i++ ) {
if (logger. isDebugEnabled ( ) ) {
logger. debug (&Target Method Arg #& + i + &: &
+ types [i ] );
return this. lookupAttributes (targetClazz. getMethod (targetMethodName, types ) );
} catch ( NoSuchMethodException nsme ) {
throw new IllegalArgumentException (&Could not obtain target method from JoinPoint: & + jp );
throw new IllegalArgumentException (& Object must be a MethodInvocation or JoinPoint& );
public boolean supports ( Class clazz ) {
return (MethodInvocation. class. isAssignableFrom (clazz )
|| JoinPoint. class. isAssignableFrom (clazz ) );
protected abstract ConfigAttributeDefinition lookupAttributes ( Method method );
我们要做的就是实现它的
protected abstract ConfigAttributeDefinition lookupAttributes(Method method);方法,
以下是我的实现方法,大致思路是这样,通过由抽象类传来的Method 对象得到
调用这个方法的 包名,类名,方法名 也就是secureObjectName, 查询数据库并将结果映射为Function 也就是secureObject ,由于Function 与 Role 的多对多关系 可以得到 Function所对应的 Roles ,在将role 包装成GrantedAuthority (也就是acegi中的角色)。其中由于频繁的对数据库的查询 所以使用Ehcache 来作为缓存。
package sample.
import java. lang. reflect. M
import java. util. ArrayL
import java. util. A
import java. util. C
import java. util. I
import java. util. L
import java. util. S
import org. acegisecurity. ConfigAttributeD
import org. acegisecurity. ConfigAttributeE
import org. acegisecurity. GrantedA
import org. acegisecurity. GrantedAuthorityI
import org. acegisecurity. intercept. method. AbstractMethodDefinitionS
import org. springframework. util. A
import sample. auth. cache. AuthorityBasedFunctionC
import sample. auth. cache. info. FunctionByNameC
import sample. dao. IBaseD
import sample. mappings. function. F
import sample. mappings. role. R
public class DatabaseDrivenMethodDefinitionSourcew extends
AbstractMethodDefinitionSource {
// baseDao 提供通过HIbenate对数据库操作的实现
private IBaseDao baseD
// AuthorityBasedFunctionCache 通过Function 查 Role 时缓存
private AuthorityBasedFunctionC
// FunctionByNameCache 由反射到的方法名查找 数据库对应的Function 时的缓存
private FunctionByNameCache functionC
public FunctionByNameCache getFunctionCache ( ) {
return functionC
public void setFunctionCache (FunctionByNameCache functionCache ) {
this. functionCache = functionC
protected ConfigAttributeDefinition lookupAttributes ( Method mi ) {
Assert. notNull (mi,&lookupAttrubutes in the DatabaseDrivenMethodDefinitionSourcew is null& );
String secureObjectName=mi. getDeclaringClass ( ). getName ( ) +&.&+ mi. getName ( );
//Function 为数据库中保护资源的映射
Function secureObject=functionCache. getFunctionByCache (secureObjectName );
if (secureObject== null ) //if secure object not exist in database
secureObject= (Function )baseDao. loadByKey (Function. class, &protectfunction&, secureObjectName );
functionCache. putFunctionInCache (secureObject );
if (secureObject== null )
Assert. notNull (secureObject,&secureObject (Function ) not found in db& );
//retrieving roles associated with this secure object
Collection roles =
GrantedAuthority [ ] grantedAuthoritys = cache. getAuthorityFromCache (secureObject. getName ( ) );
// 如果是第一次 cache 为空
if (grantedAuthoritys == null ) {
Set rolesSet = secureObject. getRoles ( );
Iterator it = rolesSet. iterator ( );
List list = new ArrayList ( );
while (it. hasNext ( ) ) {
Role role = (Role )it. next ( );
GrantedAuthority g = new GrantedAuthorityImpl (role. getName ( ) );
list. add (g );
grantedAuthoritys = (GrantedAuthority [ ] )list. toArray ( new GrantedAuthority [ 0 ] );
cache. putAuthorityInCache (secureObject. getName ( ),grantedAuthoritys );
roles = Arrays. asList (grantedAuthoritys );
roles = Arrays. asList (grantedAuthoritys );
if (!roles. isEmpty ( ) ) {
ConfigAttributeEditor configAttrEditor= new ConfigAttributeEditor ( );
StringBuffer rolesStr= new StringBuffer ( );
for ( Iterator it = roles. iterator ( );it. hasNext ( ); ) {
GrantedAuthority role= (GrantedAuthority )it. next ( );
rolesStr. append (role. getAuthority ( ) ). append (&,& );
configAttrEditor. setAsText ( rolesStr. toString ( ). substring ( 0,rolesStr. length ( )- 1 ) );
ConfigAttributeDefinition configAttrDef= (ConfigAttributeDefinition )configAttrEditor. getValue ( );
return configAttrD
Assert. notEmpty (roles,&collection of roles is null or empty& );
public Iterator getConfigAttributeDefinitions ( ) {
public IBaseDao getBaseDao ( ) {
return baseD
public void setBaseDao (IBaseDao baseDao ) {
this. baseDao = baseD
public AuthorityBasedFunctionCache getCache ( ) {
public void setCache (AuthorityBasedFunctionCache cache ) {
this. cache =
2:定义 基于方法的 自定义标志
通过以上的分析 , 要想使用acegi 做页面的显示控制仅仅靠角色(Role)是不行的,因为用户可能随时定义出新的角色,所以只能 基于方法(Function)的控制。可是acegi 只是提供了基于 角色的 接口GrantedAuthority ,怎么办?
,如法炮制。 首先定义出我们自己的GrantedFunction,实现也雷同 GrantedAuthorityImpl
package sample.
import java. io. S
public class GrantedFunctionImpl implements GrantedFunction , Serializable {
//~ Constructors ===========================================================
public GrantedFunctionImpl ( String function ) {
super ( );
this. function =
protected GrantedFunctionImpl ( ) {
throw new IllegalArgumentException (&Cannot use default constructor& );
//~ Methods ================================================================
public String getFunction ( ) {
return this.
public boolean equals ( Object obj ) {
if (obj instanceof String ) {
return obj. equals (this. function );
if (obj instanceof GrantedFunction ) {
GrantedFunction attr = (GrantedFunction )
return this. function. equals (attr. getFunction ( ) );
public int hashCode ( ) {
return this. function. hashCode ( );
public String toString ( ) {
return this.
以下是我的标志实现,大致思路是 根据 页面 的传来的 方法名(即 FunctionName)查询出对应的Functions,并且包装成grantedFunctions ,然后根据用户的角色查询出用户对应的Functions ,再取这两个集合的交集,最后再根据这个集合是否为空判断是否显示标志体的内容。
package sample.
import java. util. A
import java. util. C
import java. util. C
import java. util. HashS
import java. util. I
import java. util. L
import java. util. S
import javax. servlet. jsp. JspE
import javax. servlet. jsp. tagext. T
import javax. servlet. jsp. tagext. TagS
import org. acegisecurity. A
import org. acegisecurity. GrantedA
import org. acegisecurity. context. SecurityContextH
import org. springframework. util. StringU
import org. springframework. web. util. ExpressionEvaluationU
import sample. web. action. AppC
* @author limq
public class AuthorizeActionTag extends TagSupport {
private String ifAllGranted = &&;
private String ifAnyGranted = &&;
private String ifNotGranted = &&;
public void setIfAllGranted ( String ifAllGranted ) throws JspException {
this. ifAllGranted = ifAllG
public String getIfAllGranted ( ) {
return ifAllG
public void setIfAnyGranted ( String ifAnyGranted ) throws JspException {
this. ifAnyGranted = ifAnyG
public String getIfAnyGranted ( ) {
return ifAnyG
public void setIfNotGranted ( String ifNotGranted ) throws JspException {
this. ifNotGranted = ifNotG
public String getIfNotGranted ( ) {
return ifNotG
public int doStartTag ( ) throws JspException {
if ( ( ( null == ifAllGranted ) || &&. equals (ifAllGranted ) )
&& ( ( null == ifAnyGranted ) || &&. equals (ifAnyGranted ) )
&& ( ( null == ifNotGranted ) || &&. equals (ifNotGranted ) ) ) {
return Tag. SKIP_BODY;
final Collection granted = getPrincipalFunctionByAuthorities ( );
final String evaledIfNotGranted = ExpressionEvaluationUtils
. evaluateString (&ifNotGranted&, ifNotGranted, pageContext );
if ( ( null != evaledIfNotGranted ) && !&&. equals (evaledIfNotGranted ) ) {
Set grantedCopy = retainAll (granted,
parseSecurityString (evaledIfNotGranted ) );
if (!grantedCopy. isEmpty ( ) ) {
return Tag. SKIP_BODY;
final String evaledIfAllGranted = ExpressionEvaluationUtils
. evaluateString (&ifAllGranted&, ifAllGranted, pageContext );
if ( ( null != evaledIfAllGranted ) && !&&. equals (evaledIfAllGranted ) ) {
if (!granted. containsAll (parseSecurityString (evaledIfAllGranted ) ) ) {
return Tag. SKIP_BODY;
final String evaledIfAnyGranted = ExpressionEvaluationUtils
. evaluateString (&ifAnyGranted&, ifAnyGranted, pageContext );
if ( ( null != evaledIfAnyGranted ) && !&&. equals (evaledIfAnyGranted ) ) {
Set grantedCopy = retainAll (granted,
parseSecurityString (evaledIfAnyGranted ) );
if (grantedCopy. isEmpty ( ) ) {
return Tag. SKIP_BODY;
return Tag. EVAL_BODY_INCLUDE;
* 得到用户的Authentication,并且从Authentication中获得 Authorities,进而得到 授予用户的 Function
private Collection getPrincipalFunctionByAuthorities ( ) {
Authentication currentUser = SecurityContextHolder. getContext ( )
. getAuthentication ( );
if ( null == currentUser ) {
return Collections. EMPTY_LIST;
if ( ( null == currentUser. getAuthorities ( ) )
|| (currentUser. getAuthorities ( ). length & 1 ) ) {
return Collections. EMPTY_LIST;
// currentUser.getAuthorities() 返回的是 GrantedAuthority[]
List granted = Arrays. asList (currentUser. getAuthorities ( ) );
AuthDao authDao = (AuthDao ) AppContext. getInstance ( ). getAppContext ( ). getBean (&authDao& );
Collection grantedFunctions = authDao. getFunctionsByRoles (granted );
return grantedF
* 得到用户功能(Function)的集合,并且验证是否合法
* @param c Collection 类型
* @return Set类型
private Set SecurityObjectToFunctions ( Collection c ) {
Set target = new HashSet ( );
for ( Iterator iterator = c. iterator ( ); iterator. hasNext ( ); ) {
GrantedFunction function = (GrantedFunction ) iterator. next ( );
if ( null == function. getFunction ( ) ) {
throw new IllegalArgumentException (
&Cannot process GrantedFunction objects which return null from getFunction ( ) - attempting to process &
+ function. toString ( ) );
target. add (function. getFunction ( ) );
* 处理页面标志属性 ,用' ,'区分
private Set parseSecurityString ( String functionsString ) {
final Set requiredFunctions = new HashSet ( );
final String [ ] functions = StringUtils
. commaDelimitedListToStringArray (functionsString );
for ( int i = 0; i & functions. i++ ) {
String authority = functions [i ];
// Remove the role's whitespace characters without depending on JDK 1.4+
// Includes space, tab, new line, carriage return and form feed.
String function = StringUtils. replace (authority, & &, && );
function = StringUtils. replace (function, &\t&, && );
function = StringUtils. replace (function, &\r&, && );
function = StringUtils. replace (function, &\n&, && );
function = StringUtils. replace (function, &\f&, && );
requiredFunctions. add ( new GrantedFunctionImpl (function ) );
return requiredF
* 获得用户所拥有的Function 和 要求的 Function 的交集
浏览: 3170452 次
来自: 杭州
: wifi,ip定位,google似乎不能返回数据了,现在我们都 ...
: 求喷码器软件; java程序向喷码器输送字符,喷码器喷出来。 ...
: 引用[list][url][flash=200,200][fl ...
: 太有用了,谢谢分享!
: 支持视频会议!!我们公司现在就在用视频会议turbomeeti ...
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。若作者同意转载,必须以超链接形式标明文章原始出处和作者。
& 2003-. All rights reserved. [ 京ICP证110151号 京公网安备 ]
用手机扫描以上二维码直接访问此文。
系统分类:&>>&10055人阅读
许多 Web 应用程序要求在用户登录之后才授予其对受限制内容的访问权限。&在某些应用程序中,即使是登录的用户,也会限制他们可以查看的内容或可以编辑的字段。
要限制对 ASP.NET MVC 视图的访问,您可以限制对呈现视图的操作方法的访问。&为此,MVC 框架提供&AuthorizeAttribute&类。
有关使用特性的更多信息,请参见。
本主题包含以下各节:
当您使用&AuthorizeAttribute&标记一个操作方法时,则限制只有经过身份验证和授权的用户才能访问该操作方法。&如果您使用该特性标记控制器,则限制控制器中的所有操作方法。
Authorize&特性允许您指明将授权限制给预定义角色或各个用户。&这使您可以高度控制谁有权查看网站上的任何页面。
如果未经授权的用户尝试访问用&Authorize&特性标记的方法,则 MVC 框架会返回 401 HTTP 状态代码。&如果站点配置为使用
ASP.NET Forms 身份验证,401 状态代码会导致浏览器将用户重定向到登录页。
如果从&AuthorizeAttribute&类派生,则派生的类型必须为线程安全的类型。&因此,不要在类型本身的实例中存储状态(例如在实例字段中),除非该状态要应用于所有请求。&而是将每个请求的状态存储在&&属性中,可通过传递到AuthorizeAttribute&的上下文对象访问该属性。
[HandleError]
public class HomeController : Controller
public ActionResult Index()
ViewData[&Message&] = &Welcome to ASP.NET MVC!&;
return View();
public ActionResult About()
return View();
[Authorize]
public ActionResult AuthenticatedUsers()
return View();
[Authorize(Roles = &Admin, Super User&)]
public ActionResult AdministratorsOnly()
return View();
[Authorize(Users = &Betty, Johnny&)]
public ActionResult SpecificUserOnly()
return View();
}自定义AuthorizeAttribute
网站的权限判断是一个非常普遍的需求,从文章中我们知道实现这样的需求只要从集成,重写相关的判断逻辑就可以了。这里记录一下:
namespace TokenAcl.Web.Helper
public class TokenAclAuthorizeAttribute : AuthorizeAttribute
protected override bool AuthorizeCore(HttpContextBase httpContext)
bool result =
if (httpContext == null)
throw new ArgumentNullException(&httpContext&);
string[] users = Users.Split(',');
string[] roles = Roles.Split(',');
if (!httpContext.User.Identity.IsAuthenticated)
if (roles.Length != 0)
List&Role& rightRoles = RightClient.GetAllRole(TakenAclMenu.SystemID, TakenAclMenu.UserID);
foreach (var role in roles)
if (rightRoles.Where(x =& x.Code == role).Count() & 0)
if (!result)
httpContext.Response.StatusCode = 403;
public override void OnAuthorization(AuthorizationContext filterContext)
base.OnAuthorization(filterContext);
if (filterContext.HttpContext.Response.StatusCode == 403)
filterContext.Result = new RedirectResult(&/Admin/Dashboard&);
从AuthorizeAttribute继承过来实现了一个类TokenAclAuthorizeAttribute ,重写了方法AuthorizeCore,使用自己开发的权限系统进行权限的验证,如果没有通过认证,这表示没有权限访问,设置为403。 这样还是不行,还得重写另一个方法OnAuthorization。AuthorizeCore方法返回false,MVC 此时将返回的ActionResult是HttpUnauthorizedResult:
public class HttpUnauthorizedResult : ActionResult {
public override void ExecuteResult(ControllerContext context) {
if (context == null) {
throw new ArgumentNullException(&context&);
// 401 is the HTTP status code for unauthorized access - setting this
// will cause the active authentication module to execute its default
// unauthorized handler
context.HttpContext.Response.StatusCode = 401;
从HttpUnauthorizedResult的源码可以看出,HttpUnauthorizedResult的执行很简单,就是设置当前的HttpContext.Response的状态码为401,这样就回激活authentication module 执行它默认的 unauthorized handler,也就是跳转到登陆页面的,这似乎也不符合逻辑,认证和授权应该是验证的两个方面。这不符合要求,用户已经登陆成功了,只是没有权限而已。我这里只是重写OnAuthorization方法,重定向到一个页面而已,也可以写一个ActionResult。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:600083次
积分:7336
积分:7336
排名:第2471名
原创:115篇
转载:210篇
评论:104条
本人家乡是宁德,现在福州工作. 如果您觉得这系列的文章对你有所帮助,
欢迎打赏。
支付宝打赏
(1)(1)(4)(4)(6)(2)(2)(4)(10)(4)(3)(4)(13)(1)(1)(15)(1)(5)(1)(1)(2)(1)(1)(7)(1)(2)(14)(37)(1)(8)(3)(2)(4)(2)(1)(12)(8)(2)(1)(2)(6)(4)(9)(6)(17)(1)(4)(6)(2)(23)(7)(4)(3)(2)(6)(2)(2)(1)(2)(1)(4)(1)(1)(3)(18)请教MVC 怎么实现角色和用户的管理 - ASP.NET&&&&>>&& 请问MVC 如何实现角色和用户的管理初学mvc,貌似是在controller或其中的action中添加个[Authorize=""]
请教大牛们关于.net网站的角色,权限问题
------解决方案--------------------引用:初学mvc,貌似是在controller或其中的action中添加个[Authorize=""]
请教大牛们关于.net网站的角色,权限问题
&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&mvc
&&&&&&&&&&&&&&&&&&.net
&&&&&&&&&&&&&&&&&&权限
&&&&&&&&&&&&&&&&&&用户
&&&&&&&&&&&……
&public&class&HomeController&:&Controller
&&&&&public&ActionResult&Index()
&&&&&&&&&ViewData["Message"]&=&"Welcome&to&ASP.NET&MVC!";
&&&&&&&&&return&View();
&&&&&public&ActionResult&About()
&&&&&&&&&return&View();
&&&&&[Authorize]
&&&&&public&ActionResult&AuthenticatedUsers()
&&&&&&&&&return&View();
&&&&&[Authorize(Roles&=&"Admin,&Super&User")]
&&&&&public&ActionResult&AdministratorsOnly()
&&&&&&&&&return&View();
&&&&&[Authorize(Users&=&"Betty,&Johnny")]
&&&&&public&ActionResult&SpecificUserOnly()
&&&&&&&&&return&View();
&}------解决方案--------------------你说的很对,默认是保存在程序目录下的AppData目录下的mdf文件中,可以在web.config中指定。------解决方案--------------------
引用:引用:初学mvc,貌似是在controller或其中的action中添加个[Authorize=""]
请教大牛们关于.net网站的角色,权限问题
&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&mvc
&&&&&&&&&&&&&&&&&&.net
&&&&&&&&&&&&&&&&&&权限
我想问下那个Mvc的密码是什么算法的,可以解码查看不

我要回帖

更多关于 shiro 判断角色 的文章

 

随机推荐