简易授权系统(1)-springMVC

本文介绍在SpringMVC环境中使用自定义注解和拦截器实现授权功能的方法,简化了用户权限控制的过程,提供了易用且优雅的授权系统。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

搭建一个web系统,最先考虑的可能就是一个登录系统。登录认证授权这是一个涉及很多方面考虑的理论,关于这个问题也有很多成熟的解决方案,比如spring-security、apache shiro等。但是,在这个框架泛滥的年代,使用这些比较繁琐的框架会带来很多学习成本。由此可见登录授权问题往往就成了新手的拦路虎,或者直接没注意造成系统的安全隐患。

登录系统按照spring-security的划分,可以分为认证和授权。认证说的简单点就是把用户提交的用户名密码校验,然后把合法的用户放到session中。授权那就是区分不同的用户和角色,从而控制对特定资源的保护。

这篇文章简单说一下在springMVC环境下的一个授权实现(不是认证吆),下一篇会说一下struts2的简单授权实现。这里也给大家分享我自己录制的一个spring-security的视频教程,能力有限教程只教大家基本理论和如何看文档。

视频下载地址:http://pan.baidu.com/s/1qWGwUOO

要限制用户对某些资源的访问,最直接的肯定就是在controller中某个方法里直接判断当前用户的用户名和角色等信息。这样简单清晰实用,简直就像一个土钢炮。但是整个项目都这样写会显得特别臃肿,不够优雅。

为了打到简单易用,我们可以使用自定义Annotation,只想在一个方法上添加一个Annotation把要限制的用户名角色等信息作为参数传给Annotation,然后配合springMVC的interceptor来完成一个简单好用的授权系统。我这里仅演示一个限制角色的简单授权。其他的可以举一反三。

首先定义一个Annotation

/**
 * 权限声明接口,通过声明可以访问的角色,来控制安全(多个角色是or的关系)
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Auth {
	String[] roles() default {};
}

*这个Annotation可以被声明到一个controller或者是controller的某个方法上,只接受一个数组类型的参数roles,表示允许访问的角色。

仅仅一个Annotation是没有作用的,要写一个支持Annotation的拦截器(关于springMVC的拦截器大家可以找些文章看看)。

/**
 * Auth Annotation支撑拦截器
 */
public class AuthSupportInterceptor implements HandlerInterceptor{
	
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		System.out.println("Authentication Annotation Support Handle preHandle--------------------");
		//得到当前用户
		HttpSession session=request.getSession();
		UserInfo user=(UserInfo)session.getAttribute("user");
		//当前用户角色编码
		List<String> urs=new ArrayList<String>();
		for(Role r:user.getRoles()){
			urs.add(r.getRoleCode());
		}
		/*
		 * Auth声明支持
		 */
		Class c=handler.getClass();
		//controller声明的处理
		Auth ac=(Auth) c.getAnnotation(Auth.class);
		if(ac!=null){
			String[] roles=ac.roles();
			for(String r:roles){
				if(urs.contains(r)){
					return true;
				}
			}
			//转发到消息提示页面
			request.setAttribute("message", "您没有执行该操作的权限!");
			request.getRequestDispatcher("/jsp/message.jsp").forward(request, response);
			return false;
		}
		//方法声明处理
		//比对uri,找到处理的方法
		String uri=request.getRequestURI();
		Method[] ms=c.getMethods();
		Method dealMethod=null;
		for(Method m:ms){
			RequestMapping rm=m.getAnnotation(RequestMapping.class);
			if(rm!=null){
				String[] vs = rm.value();
				for(String v:vs){
					if(uri.endsWith(v)){
						dealMethod=m;
						break;
					}
				}
				if(dealMethod!=null){
					break;
				}
			}
		}
		//判断方法有没有Auth声明
		if(dealMethod!=null){
			Auth au=dealMethod.getAnnotation(Auth.class);
			if(au!=null){
				String[] roles=au.roles();
				for(String r:roles){
					if(urs.contains(r)){
						return true;
					}
				}
				//转发到消息提示页面
				request.setAttribute("message", "您没有执行该操作的权限!");
				request.getRequestDispatcher("/jsp/message.jsp").forward(request, response);
				return false;
			}
		}
		return true;
	}

	public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
	}

	public void afterCompletion(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
	}

}
*核心是这样,拦截器的preHandle会把要处理请求的handler(就是controller对象)带入,这样我们就能通过反射得到controller的Annotation来完成类上注解的支持。但是,我们并不知道如何得到要处理这个请求的具体方法。所以下面就通过URI匹配找到要处理的方法(这里比较简陋,没有完全去实现spring所支持的所有合法URL类型)。然后,再通过反射得到method上面的Annotation,然后就可以完成方法上注解的支持了!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值