Shiro应用到Web Application

news2025/1/12 21:03:48

 一、权限基础

a) 认证(你是谁?)

判断你(被认证者)是谁的过程。通常被认证者提供用户名和密码。

常见的认证包含如下几种:

  • 匿名认证:允许访问资源,不做任何类型的安全检查。
  • 表单认证:访问资源之前,需要提交包含用户名和密码的表单。这是web application最常用的认证方式。这个过程一般会接合Session,只在第一次(新会话)访问资源时提交认证表单。
  • 基本HTTP认证:基于RFC 2617的一种认证方式。
  • 用户认证:Filter that allows access to resources if the accessor is a known user, which is defined as having a known principal. This means that any user who is authenticated or remembered via a 'remember me' feature will be allowed access from this filter.

b)  授权(你可以做什么?)

判断被认证者(你)是否能做什么操作的过程。

  • 端口授权:必须通过指定的某个端口才能访问资源。
  • Permission授权:Filter that allows access if the current user has the permissions specified by the mapped value, or denies access if the user does not have all of the permissions specified.
  • Role授权:Filter that allows access if the current user has the roles specified by the mapped value, or denies access if the user does not have all of the roles specified.

perms     org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
port     org.apache.shiro.web.filter.authz.PortFilter
roles     org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
ssl     org.apache.shiro.web.filter.authz.SslFilter

c)  加密

使用技术手段(如:MD5、SHA等)把待加密的数据变为密文(如:信息摘要等)过程。

d)  RBAC

基于角色的访问控制(Role-Based Access Control)。

e) Realm

data access object for an application’s security components (users,roles, permissions)

f)  Permission

最小粒度的授权,不与用户关联。
例如:导出报表、查看id号为“PO20090008”的采购单、创建FAQ。

g) Role

Permission的集合。

二、Shiro特点

  • 简单。
  • 功能强大。
  • 能独立运行,不依赖其它框架或容器。
  • 包含了认证、授权、Session管理、加密。
  • 易于扩展。

三、web application 集成Shiro

a)  数据模型

用户账号Account,可以简单的理解为用户。
一个账号可以拥有多个角色(Role)。
一个角色包含了多个权限(Permission)。

b)  创建工程,新建实体,添加与Shiro相关的Jar包

Eclipse:File--New--Other--Web--Dynamic Web Project

在 /WEB-INFO/lib/目录下添加如下Jar包

相关Jar包,http://incubator.apache.org/shiro/download.html

c)  配置web.xml,添加过滤器

<filter>
     <filter-name>ShiroFilter</filter-name>
     <filter-class>org.apache.shiro.web.servlet.IniShiroFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>ShiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

d)  INI配置

[main]
#SHA256加密
sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher

#realm
myRealm = com.xx.xx.shiro.MyShiroRealm
myRealm.credentialsMatcher = $sha256Matcher

#缓存
myRealm.authorizationCachingEnabled = true
cache=org.apache.shiro.cache.ehcache.EhCacheManager
myRealm.cacheManager=$cache

[filters]
shiro.loginUrl = /login.jsp
#authc=org.apache.shiro.web.filter.authc.FormAuthenticationFilter
authc.successUrl =/background.jsp
perms.unauthorizedUrl =/401.jsp

[urls]
/login.jsp=authc
/logout.jsp=anon
/about.jsp=anon
/background.jsp=authc

/faq/test.jsp=authc
/faq/list.jsp=authc,perms["faq:list"]
/faq/view.jsp=authc,perms["faq:view"]

位置:
配置参数可以写在web.xml文件中,也可以单独文件形式存放在本地类根路径、文件系统以及网络环境中。
Shiro INI Inline Config 和External Config

public class MyShiroRealm extends AuthorizingRealm {
    protected AuthorizationInfo doGetAuthorizationInfo(
            PrincipalCollection principals) {
        String username = (String) principals.fromRealm(
                getName()).iterator().next();
        if( username != null ){
            AccountManager accountManager = new AccountManagerImpl();
            Collection<Role> myRoles = accountManager.getRoles( username );
            if( myRoles != null ){
                SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
                for( Role each:myRoles ){
                    info.addRole(each.getName());
                    info.addStringPermissions( each.getPermissionsAsString() );
                }
                return info;
            }
        }
        return null;
    }
   
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken authcToken ) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
        String accountName = token.getUsername();
               
        //用户名密码验证
        if( accountName != null && !"".equals(accountName) ){
            AccountManager accountManager = new AccountManagerImpl();
            Account account = accountManager.get( token.getUsername() );
            if( account != null )
                return new SimpleAuthenticationInfo(
                        account.getName(),account.getPassword(), getName() );
        }
        return null;
    }
}

f)   登录页面

 <%Object obj = request.getAttribute(org.apache.shiro.web.filter.authc.
FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);
            boolean flag = false;
            String msg = "";                   
            if( obj != null ){
                if( "org.apache.shiro.authc.UnknownAccountException".equals( obj ) )
                    msg = "未知帐号错误!";
                else if("org.apache.shiro.authc.IncorrectCredentialsException".equals( obj ))
                    msg = "密码错误!";                   
                else if( "org.apache.shiro.authc.AuthenticationException".equals( obj ))
                    msg = "认证失败!";
                flag = !"".equals(msg);
            }           
            if( flag )
                out.print( msg );
%>

<form action="login.jsp" method="post">
            <br/>用户帐号:
            <input type="text"  name="username" id="username" value=""/>
            <br/>登录密码:
            <input type="password" name="password" id="password" value="" />                            <br/>
            <input value="登录" type="submit" >
</form>

g)  登出页面

<%SecurityUtils.getSubject().logout();%>

四、在Shiro中实现CAPTCHA(验证码)功能

a)  验证码表单认证过滤器

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;

public class CaptchaFormAuthenticationFilter extends FormAuthenticationFilter{
      public static final String DEFAULT_CAPTCHA_PARAM = "captcha";
      private String captchaParam = DEFAULT_CAPTCHA_PARAM;
      public String getCaptchaParam() {
        return captchaParam;
    }

      protected String getCaptcha(ServletRequest request) {
        return WebUtils.getCleanParam(request, getCaptchaParam());
    }


protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
        String username = getUsername(request);
        String password = getPassword(request);
        String captcha = getCaptcha(request);
        boolean rememberMe = isRememberMe(request);
        String host = getHost(request);       
        return new CaptchaUsernamePasswordToken(username, password, rememberMe, host,captcha);
    }
}

b)  用户名密码令牌UsernamePasswordToken

import org.apache.shiro.authc.UsernamePasswordToken;

public classCaptchaUsernamePasswordToken extends UsernamePasswordToken {
      private static final long serialVersionUID = 1L;
      private String captcha;

      public String getCaptcha() {
           return captcha;
      } 

      public void setCaptcha(String captcha) {
           this.captcha = captcha;
      }

      public CaptchaUsernamePasswordToken() {
           super();
      }

      public CaptchaUsernamePasswordToken(String username, char[] password,
                 boolean rememberMe, String host,String captcha) {        
           super(username, password, rememberMe, host);
           this.captcha = captcha;
      }
}

c)  添加AuthenticationException

public classIncorrectCaptchaException extends AuthenticationException{
      private static final long serialVersionUID = 1L;

      public IncorrectCaptchaException() {
           super();
      }

      public IncorrectCaptchaException(String message, Throwable cause) {
           super(message, cause);
      }

      public IncorrectCaptchaException(String message) {
           super(message);
      }

      public IncorrectCaptchaException(Throwable cause) {
           super(cause);
      }
}

d)  Shiro INI文件

authc= com.xx.xx.shiro.CaptchaFormAuthenticationFilter

e)  实现Realm

 protectedAuthenticationInfo doGetAuthenticationInfo(
                 AuthenticationToken authcToken ) throwsAuthenticationException {
           CaptchaUsernamePasswordToken token = (CaptchaUsernamePasswordToken) authcToken;
           String accountName = token.getUsername();
                 //验证码 验证
                 String captcha = null;
                 Object obj_captcha = SecurityUtils.getSubject().getSession().getAttribute( SessionKey.CAPTCHA );
                 Object obj_count = SecurityUtils.getSubject().getSession().getAttribute( SessionKey.LOGIN_FAILED_COUNT );
                 int failed_count = (obj_count == null || !(obj_count instanceof Integer))?0:(Integer)obj_count;
                 if( obj_captcha instanceof String)
                      captcha = (String)obj_captcha;
                 if( captcha != null && failed_count >0&& !captcha.equalsIgnoreCase( token.getCaptcha() )){
                      throw newIncorrectCaptchaException("验证码错误!");
           }

           //用户名密码验证
           if( accountName != null && !"".equals(accountName) ){
                 AccountManager accountManager = newAccountManagerImpl();
                 Account account = accountManager.get( token.getUsername() );
                 if( account != null )
                      return new SimpleAuthenticationInfo( account.getName(),account.getPassword(), getName() );
           }
           return null;
      }
}

f)   登录页面

<% Object obj = request.getAttribute(org.apache.shiro.web.filter.authc.
FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);
           boolean flag = false;
           String msg = "";                        
           if( obj != null ){
                 if( "org.apache.shiro.authc.UnknownAccountException".equals( obj ) )
                      msg = "未知帐号错误!";
                 else if("org.apache.shiro.authc.IncorrectCredentialsException".equals( obj ))
                      msg = "密码错误!";
                 else if("com.xx.xx.shiro.IncorrectCaptchaException".equals( obj ))
                      msg = "验证码错误!";
                 else if( "org.apache.shiro.authc.AuthenticationException".equals( obj ))
                      msg = "认证失败!";
                 flag = !"".equals(msg);
           }
             
           if( flag ){
                 out.print( msg );
                 Integer count = (Integer)request.getSession().getAttribute(SessionKey.LOGIN_FAILED_COUNT );
                 if( count == null )
                 count = Integer.valueOf(0);
                 count++;
                 request.getSession().setAttribute(SessionKey.LOGIN_FAILED_COUNT, count);
           }                   
%>

<form action="login.jsp" method="post">
           <br/>用户帐号:
           <input type="text"  name="username" id="username" value=""/>
           <br/>登录密码:
           <input type="password" name="password" id="password" value="" />         
           <br/>验证码:
           <input type="text" name="captcha" id="captcha" size="6"/>
           <img src="/captcha" alt="captcha" />
           <br/><input value="登录" type="submit" >
</form>

g)  CAPTCHA实现

h)      

五、代码的开发环境

JAVA1.6

Tomcat

Eclipse

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1061917.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot vue云办公系统

SpringBoot vue云办公系统 系统功能 云办公系统 登录 员工资料管理: 搜索员工 添加编辑删除员工 导入导出excel 薪资管理: 工资账套管理 添加编辑删除工资账套 员工账套设置 系统管理: 基础信息设置 部门管理 职位管理 职称管理 权限组管理 操作员管理 开发环境和技术 开发语…

JavaEE-线程进阶

模拟实现一个定时器 运行结果如下&#xff1a; 上述模拟定时器的全部代码&#xff1a; import java.util.PriorityQueue;//创建一个类&#xff0c;用来描述定时器中的一个任务 class MyTimerTask implements Comparable<MyTimerTask> {//任务执行时间private long …

数据分析视角中的商业分析学习笔记

数据分析一大堆&#xff0c;结果却是大家早就知道的结论&#xff1f;是工具和方法出问题了吗&#xff1f;真正原因可能是你的思维有误区。 为什么分析的这么辛苦&#xff0c;得出的结论大家早知道&#xff0c;谁谁都不满意&#xff1f;核心原因有3个&#xff1a; 分析之前&am…

DHCPsnooping 配置实验(2)

DHCP报文泛洪攻击 限制接收到报文的速率 vlan 视图或者接口视图 dhcp request/ dhcp-rate dhcp snooping check dhcp-request enable dhcp snooping alarm dhcp-request enable dhcp snooping alarm dhcp-request threshold 1 超过则丢弃报文 查看[Huawei]dis dhcp statistic…

使用python-opencv检测图片中的人像

最简单的方法进行图片中的人像检测 使用python-opencv配合yolov3模型进行图片中的人像检测 1、安装python-opencv、numpy pip install opencv-python pip install numpy 2、下载yolo模型文件和配置文件&#xff1a; 下载地址&#xff1a; https://download.csdn.net/down…

如何使用 AI与人工智能的定义、研究价值、发展阶段

目录 一、什么是人工智能 二、人工智能的研究价值 三、人工智能的发展阶段 一、什么是人工智能 人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;是一门研究如何使计算机能够模拟和执行人类智能活动的科学与技术。人工智能旨在开发智能代理&…

CLIP 论文逐段精读【论文精读】

00:06评价&#xfeff; 评价&#xff1a;工作clip呢自从去年2月底提出就立马火爆全场&#xff0c;他的方法出奇的简单&#xff0c;但是效果呢又出奇的好&#xff0c;很多结果和结论呢都让人瞠目结舌。比如呢作者说clip的这个迁移学习能力是非常强的&#xff0c;它预训好的这个模…

【C语言】利用数组处理批量数据(一维数组和二维数组)

前言:在前面学习的程序中使用的变量都属于基本类型&#xff0c;例如整型、字符型、浮点型数据&#xff0c;这些都是简单的数据类型。对于简单的问题&#xff0c;使用这些简单的数据类型就可以了。但是对于有些需要处理的数据&#xff0c;只用以上简单的数据类型是不够的&#x…

Obsidian插件推荐_231005

起因 十一在家整理 OB 笔记&#xff0c;发现两个超好用的插件&#xff1a;Linter & tag wrangler。 前一阵把 Obsidian 笔记用 Hexo 转换成静态网页发到 github.io 做自己 blog 网站。发现了笔记中的一些问题&#xff0c;比如 tag 过多、重复&#xff0c;markdown 格式不…

菲律宾电商市场潜力巨大,Temu迎来东南亚扩张良机!(测评补单)

从拼多多传出筹备出海扩张的消息以来&#xff0c;业界都认定其迟早要进军东南亚市场。在7月份Temu上线日本站后可以看出Temu这条扩张路线背后的商业逻辑是先占领高购买力国&#xff0c;再向中低购买力国扩张&#xff0c;所以亚洲首站选择了高购买力的日本。果然在完成日韩布局后…

零基础入门初学 Python 需要安装哪些软件?

Python是近年来备受热门的编程语言&#xff0c;其简明易读、开源免费、跨平台等特点&#xff0c;使得Python倍受喜爱&#xff0c;成为初学者及开发者心中的首选。 如果你是第一次接触Python&#xff0c;又不想繁琐地安装各种软件&#xff0c;可以尝试在线运行Python代码&#…

【RCRL充放电时间相关计算】

一. 基础知识 L、C元件称为“惯性元件”&#xff0c;即电感中的电流、电容器两端的电压&#xff0c;都有一定的“电惯性”&#xff0c;不能突然变化。充放电时间&#xff0c;不光与L、C的容量有关&#xff0c;还与充/放电电路中的电阻R有关。RC电路的时间常数&#xff1a;τRC…

【扩散模型】 DDPM和DDIM讲解

扩散模型DDPM和DDIM 扩散模型之DDPM介绍了经典扩散模型DDPM的原理和实现&#xff0c;那么生成一个样本的次数和训练次数需要一致&#xff0c;导致采样过程很缓慢。这篇文章我们将介绍另外一种扩散模型DDIM&#xff08;Denoising Diffusion Implicit Models&#xff09;&#x…

STM32CubeMX学习笔记-DAC接口使用(输出电压)

STM32CubeMX学习笔记-DAC接口使用&#xff08;输出电压&#xff09; 一、DAC简介二、DAC通道选择三、新建工程四、DAC14.1 参数配置4.2 生成代码 五、库函数六、修改main函数 原创链接 1 一、DAC简介 DAC(Digital-to-Analog Converter)&#xff0c;即数字/模拟转换模块&#x…

番外--常用文件目录类命令

------------- task00: 00&#xff1a;常用文件目录类命令1-18.&#xff08;pwd&#xff1b; cd&#xff1b;ls&#xff1b; more&#xff1b;less&#xff1b;head&#xff1b;tail&#xff1b; mkdir&#xff1b;rmdir&#xff1b;cp&#xff1b;mv&#xff1b;rm&#xff1b…

第八章 排序 三、希尔排序

目录 一、算法思想 二、例子 三、代码实现 五、验证 六、空间复杂度 七、时间复杂度 八、稳定性 一、算法思想 先追求表中元素部分有序&#xff0c;在逐渐逼近表中元素全部有序。 二、例子 1、我们要升序排列此表 2、取一个差值作为子表的划分的条件&#xff0c;希尔本…

SSM - Springboot - MyBatis-Plus 全栈体系(十九)

第四章 SpringMVC 二、SpringMVC 接收数据 1. 访问路径设置 RequestMapping 注解的作用就是将请求的 URL 地址和处理请求的方式&#xff08;handler 方法&#xff09;关联起来&#xff0c;建立映射关系。SpringMVC 接收到指定的请求&#xff0c;就会来找到在映射关系中对应的…

CTFHUB - SSRF

目录 SSRF漏洞 攻击对象 攻击形式 产生漏洞的函数 file_get_contents() fsockopen() curl_exec() 提高危害 利用的伪协议 file dict gopher 内网访问 伪协议读取文件 端口扫描 POST请求 总结 上传文件 总结 FastCGI协议 CGI和FastCGI的区别 FastCGI协议 …

盒子阴影和网页布局

盒子阴影 box-shadow: 10px 10px 10px 4px rgba(0,0,0,.3);//最后一个是透明度 传统网页布局的三种方式 标准流 就是按照规定好的默认方式排列 1.块级元素&#xff1a;div、hr、p、h1~h2、ul、ol、dl、form、table 行内元素会按照书顺序&#xff0c;从左到右顺序排列&#…

1.2 数据模型

思维导图&#xff1a; 前言&#xff1a; **1.2.1 什么是模型** - **定义**&#xff1a;模型是对现实世界中某个对象特征的模拟和抽象。例如&#xff0c;一张地图、建筑设计沙盘或精致的航模飞机都可以视为具体的模型。 - **具体模型与现实生活**&#xff1a;具体模型可以很容…