apache shiro_Apache Shiro第1部分–基础

apache shiro

Apache Shiro (最初称为JSecurity)是Java安全框架。 它被接受并于2010年成为Apache顶级项目。它的目标是功能强大且易于使用。

该项目正在积极开发中,用户和开发人员的邮件列表均处于活动状态。 最重要的区域记录在其网页上。 但是,它在文档上有很多空白。 仅从文档中就不可能学会使用大多数Shiro功能。 幸运的是,该代码的注释很好,在我尝试过的地方也很容易阅读。

Shiro的主要功能是:

  • 验证,
  • 授权,
  • 密码学
  • 会话管理。

在本文中,我们尝试演示Shiro的各种功能。 我们从简单的不安全Web应用程序开始,然后向其中添加安全功能。 所有代码均在Github上的SimpleShiroSecuredApplication项目中可用。
不安全的应用程序

不安全的应用程序代码位于unsecured_application分支中。 应用程序代表一个虚构公司的内部系统。 该公司有四个部门:

  • 管理员,
  • 修理工
  • 科学家们,
  • 销售。

每个部门都有自己的页面。 每个页面都包含用户用来完成其工作的按钮。 当用户按下按钮时,工作就完成了。 例如,任何维修人员都可以转到维修人员页面,然后按“维修冰箱”按钮。 该按钮将修复冰箱并显示成功消息。

每个用户都有自己的帐户页面。 帐户页面包含用户的私人数据。 由于不安全的应用程序尚无用户,因此帐户页面不执行任何操作。 此外,还有一个页面包含所有应用程序功能。 任何人都可以做的所有事情都可以在此页面上完成。

任何人都可以做任何工作并查看所有页面 。示例应用程序在测试类RunWaitTest中运行。 以这种方式使用单元测试不是最佳实践,但现在并不重要。 如果运行该类,则该应用程序将在http:// localhost:9180 / simpleshirosecuredapplication / url处提供。

添加身份验证

首先,我们必须验证用户的身份。 最简单,最标准的身份验证是通过用户名和密码来完成的。 用户填写其用户名和密码,然后系统验证提供的值是否与某个用户帐户匹配。

对于最简单的应用程序,将用户名和密码存储在纯文本文件中就足够了。 在更实际的情况下,用户名和密码存储在持久性存储中,或者通过其他系统(例如ldap或活动目录)进行验证。 Shiro支持所有提到的身份验证方法。 如果开箱即用的身份验证功能不足,则可以使用自己的验证实现来扩展框架。

在本章中,我们将基于用户名和密码的身份验证添加到应用程序中。 用户名和密码存储在静态纯文本Shiro ini文件中。

新要求:可以登录和注销用户。 该应用程序仅可用于登录用户。 成功登录将用户重定向到他自己的帐户页面。 所有登录用户仍然可以访问所有应用程序功能和页面。

所需步骤:

  • 添加Apache Shiro,
  • 创建登录页面,
  • 配置用户和密码,
  • 创建注销页面。

添加Apache Shiro

Shiro通过Servlet过滤器集成到Web应用程序中。 过滤器在servlet之前拦截请求和响应,并执行所有必要的任务(例如,标识当前登录的用户,将登录的用户附加到当前线程等)。 默认的Shiro筛选器提供基本的安全功能,例如:

  • 强制用户登录,
  • 执行ssl,
  • 检查页面访问权限。

如果您想了解有关默认Shiro过滤器的更多信息,那么最好的起点是DefaultFilter枚举。 它列出了所有默认可用的Shiro过滤器。 如果这些不足以满足您的需求,则可以创建自定义项。

我们将使用高度可配置的IniShiroFilter 。 它从ini文件中读取Shiro配置并初始化安全框架。 它不执行任何安全检查。 权限检查,用户登录,协议检查等都委托给默认或自定义过滤器。 IniShiroFilter仅初始化它们。

文档和javadoc中都介绍了Ini配置。 Ini文件配置包含四个部分:

  • [main]部分包含Shiro初始化。 过滤器和自定义对象在此处配置。
  • [用户]部分定义用户,密码和角色。
  • [角色]部分将角色与权限相关联。
  • [urls]节指定对应用程序页面(url)的访问权限。 这是通过将默认过滤器或自定义过滤器绑定到网址来完成的。

将Apache Shiro依赖项添加到pom.xml:

<properties><shiro.version>1.1.0</shiro.version>
</properties>
<dependencies><dependency><groupid>org.apache.shiro</groupid><artifactid>shiro-core</artifactid><version>${shiro.version}</version></dependency><dependency><groupid>org.apache.shiro</groupid><artifactid>shiro-web</artifactid><version>${shiro.version}</version></dependency>
</dependencies>

创建Shiro.ini文件并将其放在类路径中。 将web.xml配置为在每个请求之前调用IniShiroFilter:

<filter><filter-name>ShiroFilter</filter-name><filter-class>org.apache.shiro.web.servlet.IniShiroFilter</filter-class><init-param><param-name>configPath</param-name><param-value>classpath:Shiro.ini</param-value></init-param>
</filter><filter-mapping><filter-name>ShiroFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>

创建登录页面

登录页面是简单HTML页面,带有提交按钮,用户名和密码字段。 登录功能默认为Shiro authc过滤器处理。 Authc过滤器仅允许登录用户访问url。 如果用户未登录,过滤器会将其重定向到登录页面。

登录页面上的表单名称必须为“ loginform”,其提交方法必须为“ post”。 创建login.jsp页面:

<form name="loginform" action="" method="post">
<table align="left" border="0" cellspacing="0" cellpadding="3"><tr><td>Username:</td><td><input type="text" name="user" maxlength="30"></td></tr><tr><td>Password:</td><td><input type="password" name="pass" maxlength="30"></td></tr><tr><td colspan="2" align="left"><input type="checkbox" name="remember"><font size="2">Remember Me</font></td></tr><tr><td colspan="2" align="right"><input type="submit" name="submit" value="Login"></td></tr>
</table> 
</form>

为所有应用程序页面启用authc过滤器:

[main] 
# specify login page
authc.loginUrl = /simpleshirosecuredapplication/account/login.jsp# name of request parameter with username; if not present filter assumes 'username'
authc.usernameParam = user
# name of request parameter with password; if not present filter assumes 'password'
authc.passwordParam = pass
# does the user wish to be remembered?; if not present filter assumes 'rememberMe'
authc.rememberMeParam = remember# redirect after successful login
authc.successUrl  = /simpleshirosecuredapplication/account/personalaccountpage.jsp[urls]
# enable authc filter for all application pages
/simpleshirosecuredapplication/**=authc

更新: Shiro自动执行上下文相关的路径匹配。 由于SimpleShiroSecuredApplication没有设置上下文路径,因此Shiro.ini中的完整路径是必需的。 但是,如果应用程序上下文路径为/ simpleshirosecuredapplication,则路径可能是相对的:例如,简单的/ ** = authc或/account/personalaccountpage.jsp。

由于通过网络发送未加密的用户名和密码是不安全的,因此我们应强制使用ssl登录。 SSL过滤器正是这样做的。 它具有一个可选参数:ssl端口号。 如果省略了port参数,它将使用默认的ssl端口443。

在Shiro中配置ssl之前,我们必须在Web服务器上启用它。 具体操作取决于Web服务器。 我们展示了如何在Jetty中启用它。 首先,使用自签名证书创建密钥库:

keytool -genkey -keyalg RSA -alias jetty -keystore keystore -storepass secret -validity 360 -keysize 2048

回答所有问题,最后按Enter键,以使密钥库密码和密钥密码相同。

其次,将密钥库添加到项目中,并将Jetty配置为使用ssl。 Java代码在AbstractContainerTest类中可用。

现在,可以在Shiro.ini中配置ssl过滤器:

[urls]
# force ssl for login page
/simpleshirosecuredapplication/account/login.jsp=ssl[8443],authc
# enable authc filter for the all application pages; as Shiro reads urls from up to down, must be last
/simpleshirosecuredapplication/**=authc

配置用户和密码

现在,SimpleShiroSecuredApplication仅适用于登录用户。 现在,我们需要添加一些用户,以便人们可以登录。配置在Shiro.ini文件的[用户]部分中完成。 部分条目的格式为:

username = password, roleName1, roleName2, ..., roleNameN

以下部分创建七个用户,所有用户都具有相同的密码“ heslo”:

[users]
administrator=heslo,Administrator
friendlyrepairmen=heslo,repairmen
unfriendlyrepairmen=heslo,repairmen
mathematician=heslo,scientist
physicien=heslo,scientist
productsales=heslo,sales
servicessales=heslo,sales

现在可以登录到应用程序。 但是,如果用户犯了错误,则不会显示任何合理的错误消息。 此外,密码存储在纯文本文件中。

错误处理

如果用户在登录时出错,则Shiro会将其重定向回登录页面。 该页面看起来与以前完全相同,这可能会使用户感到困惑。

新要求:每次尝试登录失败后,显示错误消息。

每当发生身份验证错误时,都会引发异常。 默认情况下,表单身份验证过滤器会捕获异常并将其类名称存储在request参数中。 由于我们希望自定义发送到页面的数据,因此我们必须扩展FormAuthenticationFilter并重写setFailureAttribute方法:

@Override
protected void setFailureAttribute(ServletRequest request, AuthenticationException ae) {String message = ae.getMessage();request.setAttribute(getFailureKeyAttribute(), message);
}

用VerboseFormAuthenticationFilter替换表单授权过滤器,并将其配置为使用'simpleShiroApplicationLoginFailure'请求属性来保存错误信息:

[main]
# replace form authentication filter with verbose filter 
authc = org.meri.simpleshirosecuredapplication.servlet.VerboseFormAuthenticationFilter
# request parameter with login error information; if not present filter assumes 'shiroLoginFailure'
authc.failureKeyAttribute=simpleShiroApplicationLoginFailure

在login.jsp页面中显示错误:

<% String errorDescription = (String) request.getAttribute("simpleShiroApplicationLoginFailure");if (errorDescription!=null) {
%>
Login attempt was unsuccessful: <%=errorDescription%>
<% }
%>

当心:真实的应用程序不应显示太多的登录错误信息。 消息“尝试登录失败。” 没有更多信息通常就足够了。

散列密码

当前应用程序版本的所有密码均以纯文本格式存储。 最好只存储和比较密码哈希。

负责身份验证的对象称为领域 。 默认情况下,Shiro使用带有可插入密码匹配器的IniRealm来比较密码。 我们将用ini的SHA-256哈希替换ini中的密码,并将IniRealm配置为使用SHA-256哈希匹配器。

生成密码的SHA-256哈希:

import org.apache.shiro.crypto.hash.Sha256Hash;public static void main(String[] args) {Sha256Hash sha256Hash = new Sha256Hash("heslo");System.out.println(sha256Hash.toHex());
}

将Shiro配置为比较密码哈希而不是密码本身:

[main] 
# define matcher matching hashes instead of passwords
sha256Matcher = org.apache.shiro.authc.credential.HashedCredentialsMatcher
sha256Matcher.hashAlgorithmName=SHA-256# enable matcher in iniRealm (object responsible for authentication)
iniRealm.credentialsMatcher = $sha256Matcher

用密码哈希替换用户密码:

[users]
administrator=56b1db8133d9eb398aabd376f07bf8ab5fc584ea0b8bd6a1770200cb613ca005, Administrator
friendlyrepairmen=56b1db8133d9eb398aabd376f07bf8ab5fc584ea0b8bd6a1770200cb613ca005, repairmen
unfriendlyrepairmen=56b1db8133d9eb398aabd376f07bf8ab5fc584ea0b8bd6a1770200cb613ca005, repairmen
mathematician=56b1db8133d9eb398aabd376f07bf8ab5fc584ea0b8bd6a1770200cb613ca005, scientist
physicien=56b1db8133d9eb398aabd376f07bf8ab5fc584ea0b8bd6a1770200cb613ca005,  scientist
productsales=56b1db8133d9eb398aabd376f07bf8ab5fc584ea0b8bd6a1770200cb613ca005,        sales
servicessales=56b1db8133d9eb398aabd376f07bf8ab5fc584ea0b8bd6a1770200cb613ca005,  sales

注意:无法在ini配置中指定salt。

创建注销页面

任何具有登录功能的应用程序也应具有注销功能。 使用Shiro注销当前用户很容易,请使用以下命令:

//acquire currently logged user and log him out
SecurityUtils.getSubject().logout();

注销页面如下所示:

<%@ page import="org.apache.shiro.SecurityUtils" %>
<% SecurityUtils.getSubject().logout();%>
You have succesfully logged out.

添加授权

我们通过向应用程序添加授权来结束第一部分。 我们从限制用户访问页面开始。 任何用户都不能看到其他部门的页面。 由于用户仍然能够使用“所有应用程序功能”页面或在浏览器中编辑URL来执行任何操作,因此这仅为项目提供了部分安全性。 我们将其称为页面级授权。

然后,我们限制了用户自己执行操作的能力。 即使用户打开“所有应用程序功能”页面或在浏览器中编辑url,也将只允许他执行其部门特定的功能。 我们将其称为功能级别授权。

新要求:用户无法查看不属于他的部门的页面。 用户只能执行其部门职能。 以前的规则唯一的例外是管理员,管理员可以执行管理和修复功能。

页面授权

页面级授权是通过角色过滤器完成的。 过滤器的参数部分可以包含任意数量的角色。 登录的用户只有拥有所有提供的角色,才能访问页面。

像往常一样,在Shiro.ini文件中配置角色过滤器:

[urls]
# force ssl for login page
/simpleshirosecuredapplication/account/login.jsp=ssl[8443],authc# only users with some roles are allowed to use role-specific pages 
/simpleshirosecuredapplication/repairmen/**=authc, roles[repairman]
/simpleshirosecuredapplication/sales/**=authc, roles[sales]
/simpleshirosecuredapplication/scientists/**=authc, roles[scientist]
/simpleshirosecuredapplication/adminarea/**=authc, roles[Administrator]# enable authc filter for the all application pages; as Shiro reads urls from up to down, must be last
/simpleshirosecuredapplication/**=authc

测试安全性是否有效:以任何销售用户身份登录,单击“主页”,然后单击“维修人员页面”链接。 您会看到一个难看的错误。

我们完成页面授权,并将错误替换为重定向到错误页面。 默认的Shiro过滤器具有属性validateUrl。 如果发生未经授权的访问,过滤器会将用户重定向到指定的url。

[main]
# redirect to an error page if user does not have access rights
roles.unauthorizedUrl = /simpleshirosecuredapplication/account/accessdenied.jsp

accessdenied.jsp:

<body>
Sorry, you do not have access rights to that area.
</body>

功能授权

现在所有部门页面均已安全。 但是,任何用户仍然可以在“所有应用程序功能”页面上执行任何功能。 此外,任何登录的用户都可以编辑url,从而可以执行任何操作。 例如,如果您以销售身份登录并将https:// localhost:8443 / simpleshirosecuredapplication / masterservlet?action = MANAGE_REPAIRMEN放入url中,则该应用程序也将执行管理修复功能(然后将引发空指针异常,但存在安全漏洞)已经完成了)。

我们为每个功能分配唯一的权限 。 它们分为几组:

  • 所有权限都在“功能”组中,
  • 所有管理权限都在“管理”组中,
  • 所有修复权限都在“修复”组中,
  • 所有销售权限都在“销售”组中,
  • 所有科学许可都在“科学”组中。

Shiro支持表示为字符串的多级权限。 级别用符号“:”分隔。 例如,“功能:管理:修理工”具有三个级别:“功能”,“管理”和“修理工”。 多级权限允许轻松的权限分组。 例如,科学组属于功能组,并且包含三个权限:

  • 职能:科学:研究,
  • 功能:科学:写作文章,
  • 职能:科学:准备谈话。

操作在完成记录的用户权限之前会对其进行验证:

public String doIt() {String neededPermission = getNeededPermission();// acquire logged user and check permissionif (SecurityUtils.getSubject().isPermitted(neededPermission))return "Function " + getName() + " run succesfully.";throw new UnauthorizedException("Logged user does not have " + neededPermission + " permission");
}

注意:实现同一目标的另一种方法是通过注释。

PerformFunctionAndGoBackServlet servlet捕获授权异常并将其转换为错误消息:

private String performAction(String actionName) {try {Actions action = findAction(actionName);String result = action == null ? null : action.doIt();log.debug("Performed function with result: " + result);return result;} catch (ShiroException ex) {log.debug("Function failed with " + ex.getMessage() + " message.");return "Error: " + ex.getMessage();}
}

最后,我们需要在Shiro.ini文件中配置角色的权限。 Shiro支持通配符以用于多级权限。 因此,我们不必分别指定每个部门的许可:

[roles]
# members of departments should be able to perform all departmental functions
sales=functions:sale:*
scientist=functions:science:*
repairman=functions:repair:*# administrators are able to do all management functions and repair functions
Administrator=functions:manage:*,functions:repair:*

您现在可以在“所有应用程序功能”页面上尝试功能。 如果登录的用户没有所需的权限,则会在页面顶部显示错误消息。 此外,如果您以销售身份登录并尝试入侵https:// localhost:8443 / simpleshirosecuredapplication / masterservlet?action = MANAGE_REPAIRMEN,则会在控制台中看到错误消息(而不是成功消息)。

结束

最终的应用程序可以在Github上的“ static_authentication_and_authorization”分支中找到。

在第二部分中,我们将创建自定义领域,并将用户,密码,角色和权限从ini文件移动到数据库。 第三部分专门介绍Apache Shiro加密软件包。

参考: Apache Shiro第1部分– JCG合作伙伴 Maria Jurcovicova的基础知识,来自This is Stuff博客。


翻译自: https://www.javacodegeeks.com/2012/05/apache-shiro-part-1-basics.html

apache shiro

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

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

相关文章

js编码解码

js编码解码//对输出结果编码 function encodeStr(val) {return encodeURIComponent(encodeURIComponent(trim(val))); }// 对参数解码 function decodeStr(val) {return decodeURIComponent(decodeURIComponent(trim(val))); }后端解码 public static String urlDecode(String …

PHP 中文文件名 空格等 CURL 读取

用rawurlencode 对文件名进行编码转载于:https://www.cnblogs.com/zhaoyun4122/p/7198895.html

无显示器u盘安装centos_最新版 CentOS 8.1.1911 安装教程及常见问题图文详解

基于笔记本(华硕)操作&#xff0c;使用软碟通(UltraISO)制作的系统启动盘(U盘&#xff0c;内存大于8G)操作可自行百度&#xff0c;非常简单(或可留言&#xff0c;择情况出一期U盘制作启动盘教程)。a、登录 centos 官网下载镜像文件官网地址&#xff1a;https://www.centos.org阿…

谨慎使用JUnit的预期异常

有时&#xff0c;当我们收到对jOOQ或其他库的拉取请求时&#xff0c;人们会将单元测试中的代码更改为更“惯用的JUnit”。 特别是&#xff0c;这意味着他们倾向于更改此代码&#xff08;公认的不是那么漂亮的代码&#xff09;&#xff1a; Test public void testValueOfIntInv…

plupload使用例子

plupload使用例子1. 例子 <li><a id"uploadFile">上传</a></li>//文书上传和显示 $(function () {var uploader new plupload.Uploader({runtimes: html5,flash,silverlight,html4,// 指定上传方式browse_button: uploadFile,unique_names…

mysql获取相隔时间段的数据

思路&#xff1a;为时间段内的数据进行编序号&#xff0c;然后计算好相隔时间&#xff0c;拿到id作为搜索条件 SELECT * FROM ( SELECT (i:i1) as i, id, data_send_time FROM jl_pims_machine_time mt,(select i:0) as it where mt.company_id 1001 AND mt.machine_id 1 ord…

bom实现方块移动_从0开始实现一个俄罗斯方块

写在前面得话&#xff1a;这篇文章主要记录了我是怎么一步一步写出俄罗斯方块&#xff0c;整个代码用的函数编程&#xff0c;主要是为了让一些不熟悉es6, 面向对象写法得 新手能更容易看明白&#xff0c;全部得代码中都是一些js的基础知识&#xff0c;很容易理解。要说有点麻烦…

字符串工具类

字符串工具类import javax.servlet.http.HttpServletRequest; import java.util.UUID;public class CommonUtil {/*** param request 请求* return java.lang.String 返回路径* description 获取绝对路径* date 2021/7/14 20:45*/public static String getUrlPath(HttpServletR…

JSonP跨域请求

JSonP跨域请求 我们在通过自己的页面或程序通过ajax请求其它网站或服务时&#xff0c;会存在一个ajax直接请求普通文件存在跨域无权限访问的问题&#xff0c;甭管你是静态页面、动态网页、web服务、WCF&#xff0c;只要是跨域请求&#xff0c;一律不准。不过我们又发现&#xf…

cli3解决 ie11语法错误 vue_基于 Vue + Koa2 + MongoDB + Redis 实现一个完整的登录注册...

项目地址&#xff1a;https://github.com/caochangkui/vue-element-responsive-demo/tree/login-register通过 vue-cli3.0 Element 构建项目前端&#xff0c;Node.js Koa2 MongoDB Redis 实现数据库和接口设计&#xff0c;包括邮箱验证码、用户注册、用户登录、查看删除用户…

gwt 嵌入html_GWT和HTML5画布演示

gwt 嵌入html这是我对GWT和HTML5 Canvas的第一个实验。 我的第一个尝试是创建矩形&#xff0c;仅用几行代码就得出了这样的内容&#xff1a; 码&#xff1a; public class GwtHtml5 implements EntryPoint {static final String canvasHolderId "canvasholder";sta…

使用UIWebView载入本地或远程server上的网页

大家都知道&#xff0c;使用UIWebView载入本地或远程server上的网页&#xff0c;sdk提供了三个载入接口&#xff1a;- (void)loadRequest:(NSURLRequest *)request; - (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL; - (void)loadData:(NSData *)data MI…

css使按钮固定在界面上面

css使按钮固定在界面上面<div><div style"border-bottom: 1px solid #e7e7e7"><a class"" onclick"saveTable()" style"margin-left: 2%"><i class""></i>保存</a><a class"&q…

Spring MVC:Trgger手动验证表单对象

有时可能需要在Spring MVC Controller中使用手动验证。 使用Spring的org.springframework.validation.ValidationUtils类非常简单。 了解如何在两种不同的情况下调用验证器。 方案1 –调用验证 在这种情况下&#xff0c;我有一个带有用户名字段的用户表单。 用户名字段使用自定…

tez什么意思_传统数仓和大数据数仓的区别是什么?

概念与容器为什么先说这个&#xff0c;其实很简单&#xff1a;因为绝大多数人都把这两个概念混为一谈。然后就会出现各种各样的问题&#xff1a;oracle不是数据库么&#xff0c;怎么又是数据仓库&#xff1f;Hive不是数据仓库么&#xff1f;怎么又是数据库&#xff1f;数据仓库…

Ajax4Jsf 简单介绍

Ajax4jsf 允许开发人员将 Ajax 功能添加到 JSF 应用程序中&#xff0c;而不需要 JavaScript 或用 Ajax 图形部件替换现有的组件。这个包还允许在使用 Java 2D 库时动态地生成图像。Ajax 是一种编程技术&#xff0c;它处理只有页面的一部分需要处理而不需要重新装载整个页面的情…

华为M2平板打不开云课堂_能运行PC应用的安卓生产力平板:华为MatePad Pro 5G登场...

当手机屏幕无法承担更复杂的工作任务&#xff0c;当PC重量不能满足更随性的移动办公&#xff0c;拥有全面屏和便携优势的平板电脑或是中间值&#xff0c;但前提是其必须拥有足够强大的生产力。5月27日华为在国内上市的其首款5G平板——华为MatePad Pro 5G&#xff0c;就是5G时代…

或许你不知道的10条SQL技巧(转自58沈剑原创)

这几天在写索引&#xff0c;想到一些有意思的TIPS&#xff0c;希望大家有收获。 一、一些常见的SQL实践 &#xff08;1&#xff09;负向条件查询不能使用索引 select * from order where status!0 and stauts!1 not in/not exists都不是好习惯 可以优化为in查询&#xff1a; se…

dhtmlXGrid复选框点击事件

dhtmlXGrid复选框点击事件var mygrid; //加载初始界面 $(function () {mygrid new dhtmlXGridObject(colour);mygrid.setImagePath(getUrlPath() "/static/plugg/dhtmlx/dhtmlxGrid/codebase/imgs/");mygrid.setHeader("#master_checkbox,状态,查看,编辑,xxx,…

soa示例_SOA示例应用程序

soa示例SOA描述了一组用于创建松散耦合的&#xff0c;基于标准的&#xff0c;与业务相关的服务的模式&#xff0c;由于描述&#xff0c;实现和绑定之间的关注点分离&#xff0c;因此提供了新的灵活性。 近年来&#xff0c;至少在参与大多数信息技术活动的人们中&#xff0c;面向…