# 开发规范

# Java编码规范

# 命名规范

Package命名 [NAMING.PKG-2]

描述:

Package名必须为小写字母或数字,且必须以字母开头;

平台产品中要求包名为com.seeyon.ctp.xxx或com.seeyon.apps.xxx

xxx为应用名如collaboration、edoc ...

示例:

// CTP平台表单模块
package com.seeyon.ctp.form;

// 会议应用
package com.seeyon.apps.meeting;

Class命名 [NAMING.NCL-2]

描述:

Class名首字母必须大写,如果是某个Interface的实现,要求命名采用Interface + Impl

示例:

public interface CollaborationManager{};
public class CollaborationManagerImpl implements CollaborationManager{
}

Interface命名 [NAMING.NITF-2]

描述:

Interface命名首字母必须大写

示例:

public interface CollaborationManager{
}

Exception Class命名 [NAMING.NE-2]

描述:

Exception class命名必须以Exception结尾

示例:

public class NEFormatException extends Exception{
}

Unit Test Class命名 [NAMING.NE-2]

描述:

Unit test class命名必须以Test结尾

示例:

public class FooTest extends TestCase{
}

Enum type命名 [NAMING.NENUM-2]

描述:

Enum type命名首字母必须大写

示例:

private enum Grade { 
    A, B, C, D, F 
};

Methods命名 [NAMING.NMP-2]

描述:

Method命名首字母必须小写

示例:

public class NMFixed {
    void method () {  // FIXED
    }
}

Local variables命名 [NAMING.NLV-2]

描述:

Local variable命名首字母必须小写

示例:

private int example = 0;

常量命名 [NAMING.USF-2]

描述:

所有用 ”final”、”static” 修饰的变量命名要求全大写

示例:

public static final int SIZE = 10;
private static final Logger LOGGER;

类名禁止使用java内置类名 [NAMING.DJLO-2]

描述:

类名禁止使用java内置类名

错误示例:

public class Integer{
}

标示符禁止使用java关键字 [NAMING.DJLO-2]

描述:

标示符禁止使用java关键字

错误示例:

private String enum;
private int assert;

禁止使用sun预留包名 [NAMING.RPKG-2]

描述:

禁止使用sun预留包名

错误示例:

package java.rules.naming;

禁止仅通过大小写区分变量 [NAMING.UUVN-4]

描述:

禁止仅通过大小写区分变量

错误示例:

int foo = 9;
int Foo = 9;

# 注释规范

java文件头注释 [FORMAT.MCH-2]

描述:

所有java文件需要在文件头添加如下注释段:

/**
 * $Author$
 * $Rev$
 * $Date::                     $:
 *
 * Copyright (C) 2012 Seeyon, Inc. All rights reserved.
 *
 * This software is the proprietary information of Seeyon, Inc.
 * Use is subject to license terms.
 */
package xx.xx.xx;
import xx.xx;

java类注释 [JAVADOC.PJDC-2]

描述:

所有java类需按以下格式添加类注释:

/**
 * <p>Title: 应用模块名称</p>
 * <p>Description: 代码描述</p>
 * <p>Copyright: Copyright (c) 2012</p>
 * <p>Company: seeyon.com</p>
 */
public final class MyClass

方法注释 [JAVADOC.PJDM-2]

描述:

所有方法需按以下格式添加方法注释,继承的方法可以使用’@see’、’ @inheritDoc’ tag:

/**
  * Executes a mapped SQL SELECT statement that returns data to populate
  * a number of result objects within a certain range.
  *
  * @param id The name of the statement to execute.
  * @param skip The number of results to ignore.
  * @param max The maximum number of results to return.
  * @return A List of result objects.
  * @throws java.sql.SQLException If an error occurs.
  */

  List queryForList(String id, int skip, int max) throws SQLException;

相关校验点:

[JAVADOC.DPMT-2]** 避免无用的javadoc tag

[JAVADOC.MDJT-2]** 注释内容要有意义

[JAVADOC.PARAM-2]** 每个param都要有'@param' tag

[JAVADOC.MRDC-2]** 有返回值的方法必须使用'@return' tag

[JAVADOC.THROW-2]** 有异常抛出的方法必须使用'@throws' 或 '@exception' tag

[JAVADOC.VMCR-2]** 无返回值的方法不要有'@return' tag

[JAVADOC.BT-4]** 不允许使用javadoc中未定义的'@' tag

# 格式规范

代码长度限制 [FORMAT.LL-2]

描述:

每行代码长度不能超过120个字符

每个声明占用一个代码行 [FORMAT.OSPL-2]

描述:

每个声明占用一行代码

错误示例:

int i = a + b; return i;

正确示例:

int i = a + b;
return i;

使用括号分隔复杂表达式 [FORMAT.APAREN-3]

描述:

使用括号分隔复杂表达式提高代码可读性

错误示例:

if (i >= j && i >= 0)

正确示例:

if ((i >= j) && (i >= 0))

**避免过于复杂的判断表达式

if ( workTimeSpecials.size() > 0 && !workTimeSpecials.get(0).getIsRest().equals("0")) 
    || workTimeSpecials.size() == 0 && !isWorkDay) {
        return;
}

遇到这样的表达式,请使用Extract Local Variable提取为意义明确的变量。

** 代码缩进使用空格代替tab [FORMAT.DUT-3]**

描述:

代码缩进使用空格代替tab保证代码在非windows系统环境下的可读性

数组声明格式 [FORMAT.IAD-3]

描述:

数组声明[]放在type后面而不是变量后面

错误示例:

private String str1[]**, str2[]**, str3[]**;

正确示例:

private String []** str1, str2, str3;

**正确使用equals

错误示例:

str.equals("0");

正确示例:

"0".equals(str); // 规避str为null时的空指针异常

避免不必要的小括号 [FORMAT.UP-3]

描述:

避免不必要的小括号

错误示例:

i = (i + 2);

与文件同名的类应放在所有类声明的最前面 [FORMAT.FCN-4]

描述:

如果一个文件中定义了多个类,那么与文件同名的类作为主类应放在代码的最前面

声明中修饰符的使用应遵循正确顺序 [FORMAT.MO-4]

描述:

声明中修饰符的使用应遵循以下顺序:

annotations

public/protected/private

abstract

static

final

transient

volatile

synchronized

native

strictfp

# 前端UE编码规范

# 基本原则

  1. 兼容性

    兼容多浏览器 ((尽量兼容)IE10以上、Firefox、Chrome、Safari、Edge、信创浏览器)

    但暂不考虑跨设备的兼容,只对iPad作一定的兼容性改进。

  2. 一致性

    UE交互保持一致性

    UI风格保持一致性

    代码风格保持一致性

  3. 易测性

    应用组件开发时必须考虑易测性,为自动化测试提供方便 。

  4. 适度先进性

    谨慎引入第三方前端库,引入时需要充分考虑性能、稳定性、可维护性和技能要求。

# 页面开发规范

代码结构

jsp文件放到各Project的WebContent/WEB-INF/jsp/apps/{module}下。

Example 3.1.

f1_collaboation/WebContent/WEB-INF/jsp/apps/collaboration/listPending.jsp

命名

camel命名风格

页面结构

禁止在页面中

  1. 定义css样式。
  2. 在style属性中直接书写样式。
  3. 引入除本页面同名js之外的任何js文件。(Portal如需引入第三方js,需要评审)
  4. 使用@page import引入Java类。

HTML书写规范

  1. HTML 标签必须成对使用,base br col hr img input meta link除外。
  2. HTML里的注释:<%-- 被注释的内容 --%>。
  3. 所有的标签名必须小写。
  4. 所有的标签属性名必须小写。
  5. 所有的标签属性值都必须用双引号包起来。
  6. 书写 HTML 代码的时候代码缩进。
  7. 表现与结构完全分离,代码中不涉及任何的表现元素,如style、font、bgColor、border等。
  8. 尽可能减少 div 嵌套。
  9. 给图片加上alt标签。

规范的书写示例如下:

<html>
    <head>
    </head>
    <body>
        <div id="panel"  class="panel">
        </div>
    </body>
</html>

JSTL & EL

限制使用,只能使用循环、el、少用if。

原有的taglib逐步进行迁移

只允许使用JSTL core、JSTL fmt 和JSTL functions 的部分tag,不允许使用JSTL sql和JSTL XML。

允许使用的tag列表

  1. c:out
  2. c:url
  3. c:forEach & c:if
  4. fmt:message

# Javascript开发规范

文件

JavaScript 程序应独立保存在后缀名为 .js 的文件中。

原则上,JavaScript 代码不应该被包含在 HTML 文件中。在 HTML 中的JavaScript代码会明显增加文件大小,而且也不能对其进行缓存和压缩。

模块的公开js,放到common/js/apps/{module}下,名称为模块名称,如common/js/apps/collaboration/collaboration_pub.js;发布时将被合并到主js文件。

页面js放到WebContent/apps/{module}下,建立与jsp同名的js文件,如WebContent/apps/collaboration/listPending.js。

命名

命名总的原则为:骆驼、自然语言、英文

  1. 名称只能包含下面的字符:26个大小写字符 (A .. Z, a .. z), 数字(0 .. 9),和 下划线 (_)。不允许使用中文或特殊字符。首字母下划线只能用于私有方法和全局变量。

  2. 变量名称必须为小写字母,请使用英文名词,如department ;。对象的属性或方法名采用小驼峰式(lower camel-case),如”init”, “bindEvent”, “updatePosition”:

  3. 类的命名使用骆驼命名规则,例如:Account, EventHandler

  4. 常量必须在对象(类)或者枚举变量的前部声明。枚举变量的命名必须要有实际的意义,并且其成员 必须 使用骆驼命名规则或使用大写:

  5. 不允许使用单词简写 。私有变量名用下划线开头。如:”_current”, “_defaultConfig”

  6. 不能使用大写名称作为变量名。常量名全部大写,单词间用下划线分隔。如:”CSS_BTN_CLOSE”, “TXT_LOADING”

  7. 方法和函数名应该以动词开始如getName(),返回bool类型的函数应该以is开始,例如isEnable();不必担心长度,因为后期发布时会压缩。

    除了构造方法可以使用大写,首字母必须小写。

行长度

避免每行超过 120 个字符。当一条语句一行写不下时,请考虑折行。

缩进

缩进的单位为四个空格,避免使用 Tab 键来缩进。

注释

使用jsdoc语法书写注释。例如:

/**
 * 取得指定key的国际化资源。
 * @param {String} key 资源的key。
 * @return {String} 国际化资源文本。
 */
CTP.prototype.getMessage = function(key){
    ...
}

代码风格

遵循C++风格 (opens new window),参照下面的示例:

/**
 * 取得指定key的国际化资源。
 * @param {String} key 资源的key。
 * @return {String} 国际化资源文本。
 */
CTP.prototype.getMessage = function( key ){
    try{
        var msg= eval( '' + key );
        if( msg && arguments.length > 1 ){
        for( var i = 0; i < arguments.length - 1; i++ ) {
                var regEx = eval('messageRegEx_' + i);
                var repMe = '' + arguments[i + 1];
                if( repMe.indexOf( '$_' ) !== -1 ){
                    repMe = repMe.replace('$_', '$$_');
                }
                msg = msg.replace( regEx, repMe );
            }
        }
        return msg;
    }
    catch(e){
    }
    return "";
}

# 缓存规范

# 前端缓存的类型

版本

避免升级后受缓存的旧版本文件影响。 使用:${ctp:resSuffix()} 例如:all-min.js?V=V5_6_2015-04-29 所有的js和css引用都需要加。

启动

每一次重启后缓存失效。比如启动时生成的静态化国际化文件和Ajax存根。 目前没有提供Taglib,可使用:<%=com.seeyon.ctp.common.SystemEnvironment.getServerStartTime()%> 例如:ajaxStub.js?v=1430293037148

登录

用户每一次登录后缓存失效,比如菜单、插件等个性化缓存。 使用:${ CurrentUser !=null ? CurrentUser.etagRandom : 0} 例如:main.do?method=headerjs&login=-2043353591

不缓存

动态请求,为避免浏览器缓存,url加随机数。 如:ajax.do?method=ajaxAction&managerName=sectionManager&rnd=1277

ETAG

HTTP的机制,一般使用时间戳作为ETAG的依据。 如果是转发文件,可以用文件的最后更新时间。 比如我们正文中的图片,Ajax的存根。可以使用WebUtil的checkEtag和writeEtag来实现。

有效期

response.setDateHeader("Expires", xxx);

# H5编码规范

# 基本原则

  1. 由于jquery在移动端的开发存在性能问题,页面不允许导入jquery库;
  2. 样式需进行兼容处理;
  3. UE交互保持一致性、UI风格保持一致性、代码风格保持一致性;
  4. 谨慎引入第三方前端库,引入时需要充分考虑性能、稳定性、可维护性和技能要求。

# 页面开发规范

  1. 页面使用UTF-8编码
  2. 页面首屏数据量大小在1M以内,多余的部分需要使用异步导入的方式;
  3. 禁止ajax同步请求;
  4. 尽可能减少 div 嵌套;
  5. 样式代码不能使用CSS表达式;
  6. dom选择尽量使用ID选择;
  7. 所有的标签名必须小写;
  8. 所有的标签属性名必须小写;
  9. z-index的最高使用层级为49;
  10. 不要随意的使用position定位;
  11. link标签写在head标签内;
  12. script标签写在body标签结尾处;
  13. 国际化资源以中文简体资源为首选资源;
  14. 业务逻辑入口需放在cmp.ready回调里;
  15. 页面采用自适应屏幕宽度设置。

Example

<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">

# 代码结构

  1. html文件放到html文件夹;
  2. css文件放到css文件夹;
  3. js文件放到js文件夹;
  4. 图片文件放到img文件夹;
  5. 国际化资源文件放到i18n文件夹。

# 命名

  • camel命名风格

# 项目结构规范

project
      |----html                                  <!--html文件夹-->
            -- index.html
      |----js                                    <!--js文件夹-->
           -- index.js
      |----css                                   <!--css文件夹-->
           -- index.css
      |----img                                   <!--图片文件夹-->
      |----i18n                                  <!--国际化文件夹-->
           -- project_en.js
           -- project_zh_CN.js
           -- project_zh_TW.js
      |----s3scriptjspdata                       <!--S3编译文件夹-->
           -- project_m3_commandata.data
           -- project_wechat_commandata.data
           -- project_dingding_commandata.data

      -- manifest.json                            <!--模块配置文件-->
      -- newModule_m_api.s3js                     <!--模块消息穿透、门户待办穿透api设置文件-->

# VUE前端开发规范

# 统一开发工具

  • node.js: 只支持lts版本,当前脚手架只支持v12.22.12+ || v14.21.2+
  • 代码编辑器IDE: 统一使用vscode最新版本,尽量定期根据提示升级
  • vscode插件: 在vscode插件商店搜索vue-extpack并安装

为保持编译、构建环境一致;代码风格一致;编码规范执行,务必安装上述工具。 由于工具可能未完全某些场景,暂不做强制检查,后续目录中的规范将强制执行,否则无法提交代码。

# Code Review检查点

代码Review着重检查的点,同时也是如何写出更容易维护代码的参考

1719384270640.png

# 对外开放的API必须经过评审

对外提供的API(如表单/无流程列表/自定义控件等)必须经过评审,评估接口规范、必要性、兼容性、各平台统一,禁止私自添加开放接口

# 工程规范: webapps/static目录

  • *.html不能放在static目录,必须放在seeyon中对应应用目录中
  • static中只能放静态资源(js/css/fonts/image/json等),不能放jsp/html
  • static已经明确定义1级子目录结构,不允许修改1级目录结构
  • 标准产品应用目录统一放在static/app/下,各应用内目录结构不做强制要求
  • 标准扩展及三方扩展统一放在static/extend/下,
  • 目录命名应当遵守通用命名规范(包括第三方)
  • 新工程申请/三方产品集成时必须填写构建产物目录通过审核

static目录定义如下:

static
  - base 基础模块(如基础组件库、加密模块、错误收集、页面通信等)
  - app 各应用自己的资源(示例如下,尽量将统一模块放入统一目录)
    - collaboration
    - cap4
    - cap3
    - meeting
    - ...
    - conferrence
  - extend 扩展目录(标准扩展及第三方)
    - ia
    - leximisc
    - ...
    - ocip
    - 其它
  - WEB-INF tomcat配置文件(不能修改)

# vue规范: 如何在Vue中正确使用JSX?

vue中使用JSX语法需要安装转换依赖@vue/babel-preset-jsx @vue/babel-helper-vue-jsx-merge-props

  • 新脚手架已经集成这些配置,可直接使用@devpack/qakit/config/babel
  • 历史工程确认是否安装了上述必须依赖

vue中使用JSX只支持一些特定的写法,否则可能出现h is not defined错误,或者需要手动传递h方法,推荐以下用法由babel插件自行注入`h``

# vue组件里render方法

export default {
  render() {
    // babel插件会自动生成如下代码
    // var h = this.$createElement;
    // return h('a-button');
    return <a-button>...</a-button>
  }
}

# vue组件methods里定义的方法

  • renderXxx不能命名为_render
  • _render为vue原型内部方法,可能引发异常
export default {
  methods: {
    renderXxx() {
      // babel插件会自动生成如下代码
      // var h = this.$createElement;
      // return h('a-button');
      return <a-button>...</a-button>
    }
  }
}

# VNode方式,必须显示指定形参h,常用于Fiber组件库

const renderBar = (h) => {
  // babel插件会自动生成如下代码
  // var h = arguments[0];
  // return h('a-button');
  return <a-button>...</a-button>
}

# 通过call/apply/bind改变this, 未完全理解babel转换原理及this指向慎用

  • 将renders定义在工具函数集中管理
  • 调用时需要清楚this指向
const renders = {
  renderFoo() {
    // babel插件会自动生成如下代码
    // var h = this.$createElement;
    // return h('a-button');
    return <a-button>...</a-button>
  },
  renderBar() {
    return <a-button>...</a-button> 
  }
}
// 调用方式1,挂载为当前实例方法
export default {
  methods: {
    ...renders
  }
}
// 调用方式2,通过call/apply/bind指定this,这种方法适合公用且独立维护的render实现
export default {
  render() {
    // 注意这里必须传递当前组件的this
    return renders.renderFoo.call(this, arg1, ..., argsN);
  }
}

# 开源软件引入和漏洞自查规范

开源软件需要注意协议和本身安全漏洞,在合规范围内使用。

# 开源协议

  1. BSD许可证: 介绍: BSD许可证是一种开放源代码许可证,鼓励代码共享。它允许用户在满足一些基本条件的前提下自由地使用、修改和分发软件。 特点: 宽松的许可证,允许在商业和闭源项目中使用、修改和分发代码,无需公开源代码。 商业使用限制: 基本上没有商业使用限制,非常灵活。 使用注意事项:无

扩展说明:Apache/BSD/MIT许可证都是相对宽松的开源协议: MIT许可证是一种宽松的开源软件许可证,允许在商业和私人项目中免费使用、修改和分发软件,只需在软件中包含原版权声明和许可证文本。

  1. Mozilla公共许可证(MPL): 介绍: MPL是一种结合了GPL和MIT许可证特性的混合许可证。它允许在商业和私人项目中使用、修改和分发软件。 特点: 允许在商业项目中使用、修改和分发代码,但修改后的代码必须以MPL或类似的协议发布。 商业使用限制: 需要将修改后的代码以开源形式发布。 使用注意事项:使用时不做修改

  2. Eclipse公共许可证(EPL): 介绍: EPL是为Eclipse开发的开源项目设计的许可证。它允许用户自由使用、修改和分发软件,同时要求修改后的代码必须以EPL或类似许可证开放源代码。 特点: 适用于Eclipse开源项目,允许在商业项目中使用、修改和分发代码。 商业使用限制: 商业产品需要将修改后的代码以开源形式发布。 使用注意事项:使用时不做修改

  3. GNU宽通用公共许可证(LGPL): 介绍: LGPL是GNU通用公共许可证的一个变种,允许开发者将LGPL授权的代码与非自由软件一起使用。 特点: 允许将LGPL授权的代码链接到非自由软件中,但修改后的LGPL代码必须以LGPL或者GPL发布。 商业使用限制: 商业产品需要满足LGPL的要求,确保修改后的代码以开源形式发布。 使用注意事项:动态链接使用(比如:Hibernate,glibc)

  4. GNU通用公共许可证(GPL): 介绍: GPL是最知名的开源软件许可证之一,要求任何使用、修改和分发GPL软件的人必须以相同的许可证将其修改后的版本公开发布。 特点: 强调整个产品的开源性,要求任何使用GPL组件的商业产品都必须以GPL发布。 商业使用限制: 商业产品需要将包含的GPL组件以GPL发布。 使用注意事项:进程隔离、独立于产品进程使用

  5. GNU通用公共许可证增补条款(AGPL): 介绍: AGPL是GPL的一个扩展版本,适用于在网络上提供软件服务的情况。 特点: 要求使用、修改和分发AGPL软件的人必须以AGPL发布,包括商业产品。 商业使用限制: 商业产品需要满足AGPL的要求,包括以开源形式提供源代码。 使用注意事项:进程隔离、独立于产品进程使用(比如:Berkeley DB)

  6. 服务器端公共许可证(SSPL): 介绍: SSPL是一种相对较新的开源许可证,专为云服务和大数据应用设计。 特点: 要求在使用SSPL软件的基础上构建的云服务必须将整个服务的源代码开放。 商业使用限制: 商业产品需要满足SSPL的要求,包括以开源形式提供整个服务的源代码。 使用注意事项:避免商用(比如:mongodb、redis) 所有开源软件在做版本选择时,尽量选择成熟稳定、较新的版本,不要选择有已知高危漏洞的开源组件版本。

# 漏洞自查

已知漏洞自查方式:通过搜索引擎搜索“组件名称 CVE”关键字,查看搜索结果是否有组件的官方披露漏洞网址,确认所选版本是否有漏洞披露。(实在无法判断,可将名称、版本号、开源jar包发给安全部门通过我们的自建系统进行查询)

# 安全编码规范

详细安全解决方案参考开放平台>快速开始>安全开发规范

# 典型安全漏洞

漏洞 备注 措施
脚本注入(SQL注入) 攻击者利用 SQL注入漏洞,可以获取数据库中的多种信息(如管理员后台密码),从而脱取数据库中内容(脱库)。在特别情况下还可以修改数据库内容或者插入内容到数据库,如果数据库权限分配存在问题,或者数据库本身存在缺陷,那么攻击者可以通过SQL注入漏洞直接获取 bshell 或者服务器系统权限。 杜绝静态SQL,使用PreparedStatement
XSS攻击 通过漏洞页面在浏览器上执行 js, 从而进行一系列的操作。常见的攻击方式主要是利用 XSS 盗取用户身份,进一步获取权限,甚至利用高级攻击技巧直接攻击企业内网 。 前端传入的参数输出前要进行处理
任意文件上传 文件上传攻击被利用于上传可执行文件、脚本到服务器上,进而进一步导致服务器沦陷。 不允许应用自己实现上传,统一使用系统组件,特殊需求需报备。
路径遍历 客户端指定上传文件名,攻击者利用相对路径将文件上传到上下文目录中。 1、不允许前端传递文件名;2、前端传递的参数如果带文件名,需校验File是否在指定的目录下。
任意文件下载 任意文件读取漏洞能够读取服务器上任意的脚本代码、服务及系统的配置文件等敏感信息,造成企业代码与数据的泄漏,威胁主机安全。 不允许前端指定要下载的文件位置
越权访问/敏感信息泄漏 获取其他用户的数据,修改其他用户的信息,乃至直接获取管理员权限从而可以对整个网站的数据进行操作。 角色控制
弱口令/暴力破解 获取员工权限,拿到网站管理或内部系统权限,对进一步渗透打下基础,甚至可能直接获取系统权限。 不使用弱口令

# 安全规范

  • 单点登录的ticket绝对不允许使用登录名,不允许使用永久有效的ticket,同一用户每次生成的ticket必须不一样
  • 不要给黑客留可以不登录就根据字典暴力破解密码的口。
  • 缺省不允许使用弱口令。
  • 不允许按前端传递的人员Id进行响应,必须根据当前登录用户筛选数据。
  • URL中不允许传递用户名或密码等敏感信息,必须放到Body里用POST方式提交。
  • 敏感信息不落地,密码仅用于验证环节,不允许在内存中缓存或为了方便在Cookie或Session中存储。不允许应用在数据库、文件中存储平台或系统其它应用的密码。
  • 关于敏感信息,存储一定要加密,传输尽可能保障安全,必须使用POST提交,敏感信息不允许出现在URL中,不要在日志中输出客户的信息。
  • 必须登录才允许上传文件。
  • 最终用户上传的文件不允许进入上下文目录,不允许上传jsp文件(上传的html文件要对script进行trim)。
  • 不要为了方便就开一个口可以下载任何一个文件。
  • 管理功能必须加角色控制注解,限定角色访问。
  • Servlet和不在WEB-INF中的jsp必须报备,无需登录即可访问的入口必须控制住不进行上传、反序列化等危险操作。

# 限制无需登录的请求(before V7.1SP1)

对于无需登录即可访问的url,比如登录,可以加@NeedlessCheckLogin注解

public class MainController{
    @NeedlessCheckLogin
    public ModelAndView login(HttpServletRequest request, HttpServletResponse response) throws Exception {

    }
}

注意,上面的注解仅在7.1SP1之前可用,7.1SP1以后将匿名请求控制收归平台统一管理,原则上不允许应用随意新增无需登录的请求。

# 文件越权控制:加V

我们的很多功能对链接做了权限控制,同一个URL,不同的登录用户也不能下载。以doc插件为例,在插件的配置文件(pluginProperties.xml)中增加security.digesturl

<?xml version="1.0" encoding="utf-8"?>
<ctpConfig>
    <doc>
        <security>
            <!-- 需要做URL digest的URL注册,空格分隔1为uri地址,2为method(没有可以省略),3为digest参数名 -->
            <digesturl>/doc.do rightNew resId,frType,docLibId,docLibType,isShareAndBorrowRoot,all,edit,add,readonly,browse,list,parentCommentEnabled,parentRecommendEnable,parentVersionEnabled,flag</digesturl>
            <digesturl>/doc.do docPropertyIframe resId,docResId,frType,docLibId,docLibType,isShareAndBorrowRoot,all,edit,add,create,readonly,browse,read,list,parentCommentEnabled,parentRecommendEnable</digesturl>
            <digesturl>/doc.do docProperty _resId,docResId,frType,docLibId,docLibType,isShareAndBorrowRoot,_all,_edit,_add,_create,_readonly,_browse,_read,_list,propEditValue,_parentCommentEnabled,isPerBorrow</digesturl>
            <digesturl>/doc.do knowledgeBrowse docResId,entranceType,openFrom,docVersionId</digesturl>
        </security>
    </doc>
</ctpConfig>

处理后的链接会多出一个v参数,只有当前登录用户才能够正常访问。

# 统一权限控制

7.1SP1以后对所有的Servlet、Spring controller、Ajax、jsp、Rest、SOAP请求做了统一的权限控制。应用自行添加的JSP文件,不会被解释执行。在运行期内修改已存在的JSP文件,也会被判别为非法篡改,禁止执行。

# 数据库规范

# 数据结构设计规范

基本原则

  • 遵循第三范式,适度冗余提升性能,并保证数据的一致性。
  • 符合命名规范( 注意关键字 、长度限制)。
  • 使用正确的数据类型、合适的长度。
  • 新建的表对于频繁查询的字段需要建立索引。

命名规范

  • 表的命名:模块(缩写)+表含义,例:平台模块的表前缀为ctp_,协同模块的表前缀为col_,表单模块的表前缀为cap_。
  • 表名与字段名使用下划线区分单词,以增加可读性。在HBM文件与POJO中则去除下划线, 第一个单词的首字母小写,其后单词的首字母大写。
  • 表中相同概念的字段,应该使用相同的名字、相同的类型、相同的值域,HBM映射文件与POJO类尽量保持一致的命名。例:”创建时间“在数据库中字段名为create_time,类型为datetime;在HBM映射文件与POJO类中属性名为createTime,类型为java.util.Date。
  • 索引命名:唯一,IDX_表缩写_索引字段缩写
  • 表主键:id在数据库中为bigint类型,在POJO中为long类型,通过UUID算法生成。
  • 表外键:被引用表缩写_id。
  • 注意关键字
  • 长度限制(表名、字段名、索引名长度统一不能超过25,预留PK_前缀等)

控制单表字段长度

单表所有VARCHAR类型的字段长度加起来,乘以4,不能超过65535。此问题对MySQL、SQLServer有影响,Oracle不受此影响。

优化策略:以MySQL为例,尽量少用VARCHAR大字段,比如VARCHAR(1000)、VARCHAR(2000),改为LONGTEXT。

常用数据类型

下表中是我们经常用到的一些字段的类型与值域,请大家在设计数据库之前先查询一下这张表看看类似的字段是如何定义类型与值域的。

MYSQL ORACLE SQLSERVER POSTGRESQL DM KINGBASE OSCAR GBASE HBM文件 POJO类型 场景
BIGINT INTEGER BIGINT INT8 BIGINT INT8 BIGINT BIGINT long java.lang.Long 主键
DATE DATE DATETIME TIMESTAMP(0) TIMESTAMP(0) TIMESTAMP(0) TIMESTAMP(0) TIMESTAMP(0) timestamp java.util.Date 日期
DATETIME DATE DATETIME TIMESTAMP(0) TIMESTAMP(0) TIMESTAMP(0) TIMESTAMP(0) TIMESTAMP(0) timestamp java.util.Date 日期时间
DECIMAL NUMBER NUMERIC NUMERIC NUMBER NUMERIC NUMBER NUMBER double java.lang.Double 小数
INT INTEGER INT INT4 INT INT4 INTEGER INT integer java.lang.Integer 整数
LONGBLOB BLOB IMAGE BYTEA BLOB BYTEA BLOB BLOB string java.lang.String 二进制对象
LONGTEXT CLOB NTEXT TEXT CLOB TEXT CLOB CLOB string java.lang.String 大文本
SMALLINT NUMBER(4) SMALLINT INT2 SMALLINT INT2 SMALLINT SMALLINT integer java.lang.Integer 数字枚举
VARCHAR VARCHAR2 NVARCHAR VARCHAR VARCHAR VARCHAR VARCHAR VARCHAR string java.lang.String 文本

常用字段定义规范

字段名 中文名 类型(mysql) 描述
Id 主键id bigint(20)
subject 标题 varchar(255) 长度统一定义为255,js前段校验为80
content 正文 longtext 大文本
description 描述 varchar(2000) 长度统一定义为2000,js前段校验为500
create_member_id 创建人id bigint(20) 人员表id
update_member_id 修改人id bigint(20) 人员表id
create_time 创建时间 datetime yyyy-MM-dd HH:mm:ss
update_time 修改时间 datetime yyyy-MM-dd HH:mm:ss

禁止

  • 禁止三表以上联查,容易导致性能问题。
  • 数据存储不要使用XML,避免序列化和反序列化性能问题。如果必须存储复合数据,建议使用JSON。
  • 数据类型不要使用BLOB,非结构化数据请使用文件存储。
  • 禁止循环SQL操作
  • 禁止大字段查询
  • 禁止不分页查询

# 数据结构变更规范

**修改字段类型:**原则上不允许修改,除非必须修改且数据库允许修改且已产生数据不影响的前提下,建议增加新字段兼容

**修改字段长度:**允许修改,原则只能加长,不可缩短

**修改字段名称:**建议不修改,一般用于支持新数据库时因为使用了关键字必须修改

**调整索引:**根据查询条件,优化索引,提升查询效率,注意索引长度限制

# 代码版本管理

# 代码提交规范

原则:只提交代码文件和产品所需的资源文件,其余文件一律不允许提交!

# 禁止提交的文件

  1. 禁止提交以.开始的任何文件和目录 如:

    • IDE生成的目录 .idea目录 .eclipse目录

    • 版本管理系统本地配置信息 .svn目录 .git目录

    • 项目管理工具(maven、gradle)的临时目录 .gradle目录 .mvn目录

    • eclipse配置信息 .classpath文件 .project文件 .settings文件

  2. 禁止提交和本地工程信息相关的任何文件 如:

    • 项目配置信息文件 project.iml文件 project.proj文件
  3. 编译产生的文件 如:

    • java编译产生的目录 build目录 target目录 out目录
  4. 打包工具产生的依赖目录 如:

    • nodejs的依赖目录 node_modules目录
  5. 动态生成的文件 如:

    • webpack构建生成的静态文件 static/js/app.39c23dbe587ebf1cebed.js
  6. DEMO文件、文档 如:

    • 开源工具使用到的示例(请上传到项目文档SVN) DEMO目录 README文件
  7. 其他所有非工程构建、编译、测试所需要的文件

# 提交信息

  1. 每次提交必须填写大于8个字符的提交信息
  2. 提交信息内容必须能表明本次提交的内容,禁止无意义的提交信息。
创建人:admin
修改人:het