Spring mvc的自定义注解权限拦截器(一)

2 篇文章 1 订阅
2 篇文章 0 订阅

这个是一个自定义权限拦截器,虽说有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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值