Shiro入门这篇就够了【Shiro的基础知识、回顾URL拦截】(二)

简介: 本文主要讲解的知识点有以下: 权限管理的基础知识 模型 粗粒度和细粒度的概念 回顾URL拦截的实现 Shiro的介绍与简单入门

三、回顾URL拦截


我们在学习的路途上也是使用过几次URL对权限进行拦截的

当时我们做了权限的增删该查的管理系统,但是在权限表中是没有把资源添加进去,我们使用的是Map集合来进行替代的

http://blog.csdn.net/hon_3y/article/details/61926175

随后,我们学习了动态代理和注解,我们也做了一个基于注解的拦截

  • 在Controller得到service对象的时候,service工厂返回的是一个动态代理对象回去
  • Controller拿着代理对象去调用方法,代理对象就会去解析该方法上是否有注解
  • 如果有注解,那么就需要我们进行判断该主体是否认证了,如果认证了就判断该主体是否有权限
  • 当我们解析出该主体的权限和我们注解的权限是一致的时候,才放行!

http://blog.csdn.net/hon_3y/article/details/70767050

流程:

3.jpg

这里写图片描述


3.1认证的JavaBean

我们之前认证都是放在默认的Javabean对象上的,现在既然我们准备学Shiro了,我们就得专业一点,弄一个专门存储认证信息的JavaBean

/**
 * 用户身份信息,存入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;
    }
}


认证的服务

@Override
    public ActiveUser authenticat(String userCode, String password)
            throws Exception {
        /**
    认证过程:
    根据用户身份(账号)查询数据库,如果查询不到用户不存在
    对输入的密码 和数据库密码 进行比对,如果一致,认证通过
         */
        //根据用户账号查询数据库
        SysUser sysUser = this.findSysUserByUserCode(userCode);
        if(sysUser == null){
            //抛出异常
            throw new CustomException("用户账号不存在");
        }
        //数据库密码 (md5密码 )
        String password_db = sysUser.getPassword();
        //对输入的密码 和数据库密码 进行比对,如果一致,认证通过
        //对页面输入的密码 进行md5加密 
        String password_input_md5 = new MD5().getMD5ofStr(password);
        if(!password_input_md5.equalsIgnoreCase(password_db)){
            //抛出异常
            throw new CustomException("用户名或密码 错误");
        }
        //得到用户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;
    }

Controller处理认证,如果身份认证成功,那么把认证信息存储在Session中

@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 CustomException("验证码输入错误");
        }
        //调用service校验用户账号和密码的正确性
        ActiveUser activeUser = sysService.authenticat(usercode, password);
        //如果service校验通过,将用户身份记录到session
        session.setAttribute("activeUser", activeUser);
        //重定向到商品查询页面
        return "redirect:/first.action";
    }


身份认证拦截器

//在执行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;
            }
        }
        //判断用户身份在session中是否存在
        HttpSession session = request.getSession();
        ActiveUser activeUser = (ActiveUser) session.getAttribute("activeUser");
        //如果用户身份在session中存在放行
        if(activeUser!=null){
            return true;
        }
        //执行到这里拦截,跳转到登陆页面,用户进行身份认证
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
        //如果返回false表示拦截不继续执行handler,如果返回true表示放行
        return false;
    }

授权拦截器

//在执行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;
    }


拦截器配置:

<!--拦截器 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <!-- 用户认证拦截 -->
            <mvc:mapping path="/**" />
            <bean class="cn.itcast.ssm.controller.interceptor.LoginInterceptor"></bean>
        </mvc:interceptor>
        <mvc:interceptor>
            <!-- 授权拦截 -->
            <mvc:mapping path="/**" />
            <bean class="cn.itcast.ssm.controller.interceptor.PermissionInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

四、什么是Shiro

shiro是apache的一个开源框架,是一个权限管理的框架,实现 用户认证、用户授权

spring中有spring security (原名Acegi),是一个权限框架,它和spring依赖过于紧密,没有shiro使用简单。

shiro不依赖于spring,shiro不仅可以实现 web应用的权限管理,还可以实现c/s系统,分布式系统权限管理,shiro属于轻量框架,越来越多企业项目开始使用shiro。

Shiro架构:

4.jpg这里写图片描述

  • subject:主体,可以是用户也可以是程序,主体要访问系统,系统需要对主体进行认证、授权。
  • securityManager:安全管理器,主体进行认证和授权都 是通过securityManager进行。
  • authenticator:认证器,主体进行认证最终通过authenticator进行的。
  • authorizer:授权器,主体进行授权最终通过authorizer进行的。
  • sessionManager:web应用中一般是用web容器对session进行管理,shiro也提供一套session管理的方式。
  • SessionDao:  通过SessionDao管理session数据,针对个性化的session数据存储需要使用sessionDao。
  • cache Manager:缓存管理器,主要对session和授权数据进行缓存,比如将授权数据通过cacheManager进行缓存管理,和ehcache整合对缓存数据进行管理。
  • realm:域,领域,相当于数据源,通过realm存取认证、授权相关数据。
目录
相关文章
|
安全 测试技术 网络安全
软件测试|测试平台开发-Flask 入门:URL组成部分详解
软件测试|测试平台开发-Flask 入门:URL组成部分详解
|
网络架构 Python
【flask入门系列】处理请求之url 路径参数的获取以及转换器的使用
这节我们写一下url路径参数的获取以及转换器的使用,学一下如何在我们的的url路径中加参数以及如何使用转换器,并且自定义转换器。
794 0
【flask入门系列】处理请求之url 路径参数的获取以及转换器的使用
|
4月前
|
安全 Java 数据安全/隐私保护
|
Java
Shiro学习-URL配置细节(六)
Shiro学习-URL配置细节(六)
71 0
|
JavaScript 网络协议 数据安全/隐私保护
Node.js入门之url模块和querystring模块
url模块和querystring模块是非常重要的两个URL处理模块。在做node服务端的开发时会经常用到。
159 0
|
Web App开发 JavaScript 安全
window.open(url)多次打开下载链接被浏览器拦截问题解决方案,js实现循环访问多个下载链接
window.open(url)多次打开下载链接被浏览器拦截问题解决方案,js实现循环访问多个下载链接
785 0
window.open(url)多次打开下载链接被浏览器拦截问题解决方案,js实现循环访问多个下载链接
|
Go 数据安全/隐私保护
Go 语言入门很简单:net/url 包(上)
在 Golang 中,将 URL 打包用于从服务器获取数据非常重要。只需了解您是否正在处理任何应用程序并且您想从任何外部位置或服务器获取此应用程序的数据,都需要我们可以使用 URL。
Go 语言入门很简单:net/url 包(下)
在 Golang 中,将 URL 打包用于从服务器获取数据非常重要。只需了解您是否正在处理任何应用程序并且您想从任何外部位置或服务器获取此应用程序的数据,都需要我们可以使用 URL。
|
存储 算法 Java
Shiro入门这篇就够了【Shiro的基础知识、回顾URL拦截】(三)
本文主要讲解的知识点有以下: 权限管理的基础知识 模型 粗粒度和细粒度的概念 回顾URL拦截的实现 Shiro的介绍与简单入门
288 0
Shiro入门这篇就够了【Shiro的基础知识、回顾URL拦截】(三)

相关实验场景

更多