Spring mvc的自定义注解权限拦截器(一)
来源:互联网 发布:二级域名cdn后主域名 编辑:程序博客网 时间:2024/05/22 00:40
这个是一个自定义权限拦截器,虽说有Spring Security,但是还是记录下它,下篇在写Spring Security吧。
1.写两个自定义注解(功能类似于spring security的@PreAuthorize)
package com.jeff.authority;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface Auth { public String[] roles(); public String description() default ""; public String url() default "";}
package com.jeff.authority;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface AuthClass { public String[] defaultRoles() default {};}
2.具体实现权限拦截的类
package com.jeff.authority;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.HashMap;import java.util.HashSet;import java.util.Properties;import java.util.Set;import com.jeff.util.PropertiesUtil;public class AuthContext { public static HashMap<String, Set<String>> acl = new HashMap<String, Set<String>>(); public static Set<String> freeUrls = new HashSet<String>(); //不加拦截的的方法 static { freeUrls.add("/admin/login"); freeUrls.add("/admin/mobileLogin"); freeUrls.add("/user/login"); freeUrls.add("/user/logout"); freeUrls.add("/user/getQRcode"); freeUrls.add("/user/scanLoginCode"); freeUrls.add("/user/check"); freeUrls.add("/user/mobileLogin"); freeUrls.add("/user/fingerLogin"); freeUrls.add("/exam/login"); freeUrls.add("/exam/getUserIdQRcode"); freeUrls.add("/exam/getQRcode"); freeUrls.add("/exam/scanLoginCode"); freeUrls.add("/exam/examineeFingerLogin"); freeUrls.add("/ajaxmenutree"); freeUrls.add("/news/searchNewsByPage"); freeUrls.add("/news/getOneNews"); freeUrls.add("/file/downloadAttachment"); } /*** * 判断是否有权限调用该方法 * @param gradeId * @param url * @return */ public static boolean checkAuth(String gradeId, String url) {// if (acl.containsKey(gradeId))// return acl.get(gradeId).contains(url);// else// return freeUrls.contains(url); if(freeUrls.contains(url)) { return true; //先判断是否是自由访问的,如果是直接返回true } else if (acl.containsKey(gradeId)) { return acl.get(gradeId).contains(url);//返回该角色是否有权限调用此方法 } else { return false; } } /*** * 获取角色权限的信息 生成HashMap acl * @param connection * @throws SQLException */ public static void initAuthContext(Connection connection) throws SQLException { Properties properties = PropertiesUtil.getProp("jdbc.properties"); String url = properties.getProperty("jdbc_url"); String username = properties.getProperty("jdbc_username"); String password = properties.getProperty("jdbc_password"); try { if (connection == null || connection.isClosed()) connection = DriverManager.getConnection(url, username, password); Statement statement = connection.createStatement(); //将所有角色和它可以调用的方法url查询出来 String sql = "select g.id as gId,f.url as url from `grade` g,`func_permit` f where FIND_IN_SET(f.id,g.func_permit_list)"; ResultSet rs = statement.executeQuery(sql); // 添加权限对应的url串 while (rs.next()) { String gId = rs.getString("gId"); String pUrl = rs.getString("url"); Set<String> urls; /** * 将权限信息生成hash */ if (acl.containsKey(gId)){ urls = acl.get(gId); } else { urls = new HashSet<String>(); acl.put(gId, urls); } urls.add(pUrl); } rs.close(); statement.close(); connection.close(); } catch (SQLException se) { System.out.println("数据库连接失败!"); se.printStackTrace(); } }}
3.写一个拦截器,项目启动时运行
package com.jeff.authority;import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;import java.util.Properties;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;import com.jeff.util.PropertiesUtil;/** * 权限监听器、拦截器 * @author chen * */public class AuthListener implements ServletContextListener { @Override public void contextDestroyed(ServletContextEvent arg0) { } @Override public void contextInitialized(ServletContextEvent arg0) { Properties properties = PropertiesUtil.getProp("jdbc.properties"); String url = properties.getProperty("jdbc_url"); String username = properties.getProperty("jdbc_username"); String password = properties.getProperty("jdbc_password"); try { Connection con = DriverManager.getConnection(url, username, password);//数据库连接 AuthUtil.initAuth(AuthUtil.pNames, con); AuthContext.initAuthContext(con); con.close(); } catch (SQLException se) { System.out.println("数据库连接失败!"); se.printStackTrace(); } }}
4.在web.xml配置拦截器
<listener> <description>权限初始化监听器</description> <listener-class>com.jeff.authority.AuthListener</listener-class> </listener>
5.默认属性文件 authority.properties
#角色表role = grade(id,name)#用户角色表#user_role = user_grade(id,user_id,grade_id)#权限表permission = permission(id,description,URL) #权限控制表ACL(access control list)acl = acl(id,grade_id,permission_id)
6.写一个过滤器,使每次调用方法都判断权限
package com.jeff.mybatis.autobuild;import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.jeff.authority.AuthContext;import com.jeff.common.BaseInfo;import com.jeff.util.StringUtil;/** * 将分页的pager数据嵌入localthread中 * * @author jeff he * */public class LogAndPermitFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; String userId = ""; MybatisContext.setUserId(BaseInfo.GetUserId(request)); String gId = ""; String url = ""; try { String displayName = request.getContextPath();//获取项目的根路径,即项目名 System.out.println(displayName); url = request.getRequestURL().toString();//获取访问的url int i = url.indexOf("/", url.indexOf(displayName) + 1);//项目名的长度 int j = url.lastIndexOf(".do"); url = url.substring(i, j);//剪切url,去掉项目名的头,和.do的尾 //System.out.println(url); userId = BaseInfo.GetUserId(request);//获取session gId = BaseInfo.GetUserGradeId(request); if (StringUtil.isEmpty(userId)) { userId = "session中没有user"; } // 将LOG数据放入当前线程 MybatisContext.setUserId(userId); // System.out.println(MybatisContext.getUserId()); if (AuthContext.checkAuth(gId, url)){//判断是否有权限 chain.doFilter(req, resp); } else { System.out.println("目标地址:" + url + " 未授权"); request.getSession().setAttribute("info", "方法未授权,请先登录系统"); response.sendRedirect(displayName); } //chain.doFilter(req, resp); } catch (Exception e) { userId = "获取userid出现异常"; } finally { // 清除LOG数据 MybatisContext.clearContext(); } } public void init(FilterConfig cfg) throws ServletException { } public void destroy() { }}
7.在web.xml配置过滤器
<filter> <description>Log拦截器</description> <filter-name>logAndPermitFilter</filter-name> <filter-class>com.jeff.mybatis.autobuild.LogAndPermitFilter</filter-class> </filter> <filter-mapping> <filter-name>logAndPermitFilter</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping>
至此,所有权限拦截器配置已经完成,具体使用如下
1.controller 类上使用@AuthClass
@AuthClass@Controller@RequestMapping("admin")public class AdminController { ..........}
2.方法上使用@Auth
@RequestMapping("changeType") @ResponseBody @Auth(roles = { "业务主管机构"}, description = "业务主管修改当前的type类型") public ResultMap changeType(HttpServletRequest request, String type) { ........ }
0 0
- Spring mvc的自定义注解权限拦截器(一)
- SpringMVC拦截器+Spring自定义注解实现权限验证
- Spring MVC的自定义拦截器(登录)
- spring mvc 自定义拦截器
- Spring MVC自定义拦截器
- Spring MVC 自定义拦截器
- 基于注解风格的Spring-MVC的拦截器
- 基于注解风格的Spring-MVC的拦截器
- 基于注解风格的Spring-MVC的拦截器
- 基于注解风格的Spring-MVC的拦截器
- spring mvc 权限拦截
- 自定义注解+拦截器实现权限控制
- 自定义注解+拦截器实现权限控制
- spring 拦截器 spring自定义注解
- spring 拦截器 spring自定义注解
- spring mvc拦截器注意细节(基于注解)
- spring mvc 方法注解拦截器
- spring mvc 方法注解拦截器
- C语言(ACM)坑人的地方
- 方法数超出64K限制错误
- 实现spring事务的四种方式
- 我的服务器开发之路-挂载数据盘
- nested exception is IncompleteElementException: Could not find parameter map
- Spring mvc的自定义注解权限拦截器(一)
- ajax
- scanf的一些小细节
- c# 画控件圆角矩形边框
- Genymotion 2.8启动黑屏解决(mac上)
- 【bzoj 3048】[Usaco2013 Jan]Cow Lineup(单调队列)
- [BZOJ3631][洛谷P3258][JLOI2014]松鼠的新家
- sort的内部排序之快排
- 洛谷 P1656 炸铁路