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
原创粉丝点击