基于URL的权限管理(三)

 

思路:先创建一个专门的类ActiveUser用于存储用户登录的信息,主要用于存储用户id,账户,名称,菜单,权限。

认证拦截器主要是查看用户是否已登陆,如果没有转发到登陆界面,用户用账户跟密码登录时候先验证账户密码认证。

如果正确登陆之后进入授权拦截器中,授权拦截器主要查看session域中用户的菜单与权限(如果其权限满足能访问资源就放行)。用户每点一次按钮都会访问一个URL,都会进行权限的判断。

在session中存取用户信息的思路:根据用户的id去关联查询用户的菜单与权限以对象形式放入list中,并将查出来的信息存到ActiveUser,将ActiveUser存到session域中。菜单主要是进去之后左边的大菜单,菜单的URL是点击大菜单的时候跳转的页面,权限是其点击小按钮进行每一次访问的URL(也会进行处理),这样处理比较严谨。

 

 

 

1.流程

 

 

 

2.系统登陆

系统 登陆相当 于用户身份认证,用户成功,要在session中记录用户的身份信息.

 

操作流程:

         用户进行登陆页面

         输入用户名和密码进行登陆

         进行用户名和密码校验

         如果校验通过,在session记录用户身份信息

 

   2.1    用户的身份信息

创建专门类用于记录用户身份信息。

package cn.qlq.springmvc.pojo;


import java.util.Iterator;
import java.util.List;

import com.sun.org.apache.bcel.internal.generic.NEW;

/**
 * 用户身份信息,存入session 由于tomcat将session会序列化在本地硬盘上,所以使用Serializable接口
 * 
 * @author Thinkpad
 * 
 */
public class ActiveUser implements java.io.Serializable {
    private String userid;//用户id(主键)
    private String usercode;// 用户账号
    private String username;// 用户名称

    private List<SysPermission> menus;// 菜单
    private List<SysPermission> permissions;// 权限

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }


    public String getUsercode() {
        return usercode;
    }

    public void setUsercode(String usercode) {
        this.usercode = usercode;
    }

    public String getUserid() {
        return userid;
    }

    public void setUserid(String userid) {
        this.userid = userid;
    }

    public List<SysPermission> getMenus() {
        return menus;
    }

    public void setMenus(List<SysPermission> menus) {
        this.menus = menus;
    }

    public List<SysPermission> getPermissions() {
        return permissions;
    }

    public void setPermissions(List<SysPermission> permissions) {
        this.permissions = permissions;
    }

    
}

 

2.2             mapper

mapper接口: 根据用户账号查询用户(sys_user)信息(使用逆向工程生成的mapper)

查询菜单与权限的时候需要进行多表查询,自定义mapper

 

mapper.java

public interface SysPermissionMapperCustom {
    
    //根据用户id查询菜单
    public List<SysPermission> findMenuListByUserId(String userid)throws Exception;
    //根据用户id查询权限url
    public List<SysPermission> findPermissionListByUserId(String userid)throws Exception;

}

 

mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.qlq.springmvc.mapper.SysPermissionMapperCustom" >
  
  
  <!-- 根据用户id查询url -->
  <select id="findPermissionListByUserId" parameterType="string" resultType="cn.qlq.springmvc.pojo.SysPermission">
      SELECT 
      * 
    FROM
      sys_permission 
    WHERE TYPE = 'permission' 
      AND id IN 
      (SELECT 
        sys_permission_id 
      FROM
        sys_role_permission 
      WHERE sys_role_id IN 
        (SELECT 
          sys_role_id 
        FROM
          sys_user_role 
        WHERE sys_user_id = #{id}))
  </select>
  
   <!-- 根据用户id查询菜单 -->
  <select id="findMenuListByUserId"  parameterType="string" resultType="cn.qlq.springmvc.pojo.SysPermission">
          SELECT 
      * 
    FROM
      sys_permission 
    WHERE TYPE = 'menu' 
      AND id IN 
      (SELECT 
        sys_permission_id 
      FROM
        sys_role_permission 
      WHERE sys_role_id IN 
        (SELECT 
          sys_role_id 
        FROM
          sys_user_role 
        WHERE sys_user_id = #{id}))
  </select>
  
</mapper>

 

 

 

2.3 Service(进行用户名和密码校验)

 

接口功能:根据用户的身份和密码 进行认证,如果认证通过,返回用户身份信息

认证过程:

         根据用户身份(账号)查询数据库,如果查询不到用户不存在

         对输入的密码 和数据库密码 进行比对,如果一致,认证通过

 

package cn.qlq.springmvc.serviceImpl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.qlq.springmvc.Exception.MyException;
import cn.qlq.springmvc.mapper.SysPermissionMapperCustom;
import cn.qlq.springmvc.mapper.SysUserMapper;
import cn.qlq.springmvc.pojo.ActiveUser;
import cn.qlq.springmvc.pojo.SysPermission;
import cn.qlq.springmvc.pojo.SysUser;
import cn.qlq.springmvc.pojo.SysUserExample;
import cn.qlq.springmvc.service.SysService;
import cn.qlq.springmvc.utils.MD5;

/**
 * 认证和授权
 * 
 * @author: qlq
 * @date : 2017年7月28日上午10:45:52
 */
@Service
public class SysServiceImpl implements SysService {

    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysPermissionMapperCustom sysPermissionMapperCustom;

    @Override
    public ActiveUser authenticat(String userCode, String password) throws Exception {
        /**
         * 认证过程: 根据用户身份(账号)查询数据库,如果查询不到用户不存在 对输入的密码 和数据库密码 进行比对,如果一致,认证通过
         */
        // 根据用户账号查询数据库
        SysUser sysUser = this.findSysUserByUserCode(userCode);

        if (sysUser == null) {
            // 抛出异常
            throw new MyException("用户账号不存在");
        }

        // 数据库密码 (md5密码 )
        String password_db = sysUser.getPassword();

        // 对输入的密码 和数据库密码 进行比对,如果一致,认证通过
        // 对页面输入的密码 进行md5加密
        String password_input_md5 = new MD5().getMD5ofStr(password);
        if (!password_input_md5.equalsIgnoreCase(password_db)) {
            // 抛出异常
            throw new MyException("用户名或密码 错误");
        }
        // 得到用户id
        String userid = sysUser.getId();
        // 根据用户id查询菜单
        List<SysPermission> menus = this.findMenuListByUserId(userid);

        // 根据用户id查询权限url
        List<SysPermission> permissions = this.findPermissionListByUserId(userid);

        // 认证通过,返回用户身份信息
        ActiveUser activeUser = new ActiveUser();
        activeUser.setUserid(sysUser.getId());
        activeUser.setUsercode(userCode);
        activeUser.setUsername(sysUser.getUsername());// 用户名称

        // 放入权限范围的菜单和url
        activeUser.setMenus(menus);
        activeUser.setPermissions(permissions);

        return activeUser;
    }

    // 根据用户账号查询用户信息
    public SysUser findSysUserByUserCode(String userCode) throws Exception {
        // 根据用户名查询用户信息
        SysUserExample sysUserExample = new SysUserExample();
        SysUserExample.Criteria criteria = sysUserExample.createCriteria();
        criteria.andUsercodeEqualTo(userCode);

        List<SysUser> list = sysUserMapper.selectByExample(sysUserExample);

        if (list != null && list.size() == 1) {
            return list.get(0);
        }

        return null;
    }

    @Override
    public List<SysPermission> findMenuListByUserId(String userid) throws Exception {

        return sysPermissionMapperCustom.findMenuListByUserId(userid);
    }

    @Override
    public List<SysPermission> findPermissionListByUserId(String userid) throws Exception {

        return sysPermissionMapperCustom.findPermissionListByUserId(userid);
    }
}

 

 

2.4      controller(记录session)

 

package cn.qlq.springmvc.controller;


import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import cn.qlq.springmvc.Exception.MyException;
import cn.qlq.springmvc.pojo.ActiveUser;
import cn.qlq.springmvc.service.SysService;

@Controller
public class LoginController {
    
    @Autowired
    private SysService sysService;
    
    
    //用户登陆提交方法
    /**
     * 
     * <p>Title: login</p>
     * <p>Description: </p>
     * @param session
     * @param randomcode 输入的验证码
     * @param usercode 用户账号
     * @param password 用户密码 
     * @return
     * @throws Exception
     */
    @RequestMapping("/login")
    public String login(HttpSession session, String randomcode,String usercode,String password)throws Exception{
        
        //校验验证码,防止恶性攻击
        //从session获取正确验证码
        String validateCode = (String) session.getAttribute("validateCode");
        
        //输入的验证和session中的验证进行对比 
        if(!randomcode.equals(validateCode)){
            //抛出异常
            throw new MyException("验证码输入错误");
        }
        
        //调用service校验用户账号和密码的正确性
        ActiveUser activeUser = sysService.authenticat(usercode, password);
        
        //如果service校验通过,将用户身份记录到session
        session.setAttribute("activeUser", activeUser);
        //重定向到商品查询页面
        return "redirect:/first.action";
    }
    
    //用户退出
    @RequestMapping("/logout")
    public String logout(HttpSession session)throws Exception{
        
        //session失效
        session.invalidate();
        //重定向到商品查询页面
        return "redirect:/first.action";
        
    }
    

}

 

 

 

 

2.5     用户认证拦截器

 

package cn.qlq.springmvc.inteceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/**
 * SpringMVC的拦截器
* @author: qlq
* @date :  2017年7月22日下午12:20:52
 */
public class Inteceptor1 implements HandlerInterceptor{


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
//        判断是否是登陆
        String requestURI = request.getRequestURI();  //springmvc-mybatis/itemlist.action
        StringBuffer requestURL = request.getRequestURL(); //http://localhost:8080/springmvc-mybatis/itemlist.action
//        判断用户是否登陆  如果没有登陆  重定向到登陆页面   不放行   如果登陆了  就放行了
        if(!requestURI.contains("login")){
            Object attribute = request.getSession().getAttribute("user");
            if(attribute==null){
                response.sendRedirect(request.getContextPath()+"/login.action");
                return false;
            }
        }
        //不放行的话返回false
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
            throws Exception {
        System.out.println("这是方法后1");        
    }
    @Override
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {
        // TODO Auto-generated method stub
        System.out.println("这是页面渲染后1");
    }



    
}

 

 

 2.6用户授权拦截器(在认证拦截器之后配置)

package cn.qlq.springmvc.inteceptor;



import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import cn.qlq.springmvc.pojo.ActiveUser;
import cn.qlq.springmvc.pojo.SysPermission;
import cn.qlq.springmvc.utils.ResourcesUtil;



public class PermissionInterceptor implements HandlerInterceptor {

    //在执行handler之前来执行的
    //用于用户认证校验、用户权限校验
    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
        
        //得到请求的url
        String url = request.getRequestURI();
        
        //判断是否是公开 地址
        //实际开发中需要公开 地址配置在配置文件中
        //从配置中取逆名访问url
        
        List<String> open_urls = ResourcesUtil.gekeyList("anonymousURL");
        //遍历公开 地址,如果是公开 地址则放行
        for(String open_url:open_urls){
            if(url.indexOf(open_url)>=0){
                //如果是公开 地址则放行
                return true;
            }
        }
        
        //从配置文件中获取公共访问地址
        List<String> common_urls = ResourcesUtil.gekeyList("commonURL");
        //遍历公用 地址,如果是公用 地址则放行
        for(String common_url:common_urls){
            if(url.indexOf(common_url)>=0){
                //如果是公开 地址则放行
                return true;
            }
        }
        
        //获取session
        HttpSession session = request.getSession();
        ActiveUser activeUser = (ActiveUser) session.getAttribute("activeUser");
        //从session中取权限范围的url
        List<SysPermission> permissions = activeUser.getPermissions();
        for(SysPermission sysPermission:permissions){
            //权限的url
            String permission_url = sysPermission.getUrl();
            if(url.indexOf(permission_url)>=0){
                //如果是权限的url 地址则放行
                return true;
            }
        }
        
        //执行到这里拦截,跳转到无权访问的提示页面
        request.getRequestDispatcher("/WEB-INF/jsp/refuse.jsp").forward(request, response);
        
        //如果返回false表示拦截不继续执行handler,如果返回true表示放行
        return false;
    }
    //在执行handler返回modelAndView之前来执行
    //如果需要向页面提供一些公用 的数据或配置一些视图信息,使用此方法实现 从modelAndView入手
    @Override
    public void postHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println("HandlerInterceptor1...postHandle");
        
    }
    //执行handler之后执行此方法
    //作系统 统一异常处理,进行方法执行性能监控,在preHandle中设置一个时间点,在afterCompletion设置一个时间,两个时间点的差就是执行时长
    //实现 系统 统一日志记录
    @Override
    public void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("HandlerInterceptor1...afterCompletion");
    }

}

 

 

 

源码地址:

 

 https://github.com/qiao-zhi/quanxian.git

 

posted @ 2017-07-28 18:17  QiaoZhi  阅读(1138)  评论(0编辑  收藏  举报