三级等保测评,如何通过

  • 引言
  • 所需准备
  • 服务器整改(硬件部分)
    • 1.添加三员,且三权必须分离
    • 2.密码复杂度
    • 3.登录失败、超时处理
    • 4.日志转存至日志审计
  • 服务器整改(业务服务器)
    • 1.数据库整改(以我的项目为例springboot+mybatis+pgsql)
    • 2.加密
    • 4.敏感信息过滤筛选
  • 客户端整改
    • 1.敏感信息脱敏处理
    • 2.参数验证
    • 3.密码规则

引言

你好!本文旨在帮助想要过三级等保测评的项目一些指引,尽量避免在整改过程中走弯路和碰壁。
以及提醒开发者,项目中的哪些东西需要尽早完成,避免在项目成型后再去改变架构从而影响到项目的稳定性、可维护性等等。就算你本身并不是网络安全工程师(本人是个普通的JAVA后端工程师),业务服务器整改以JAVA为例子,但就算你的项目并非JAVA作为服务器,本文提供的解决方案依旧通用,只是具体实现需要你自行完成,根据本篇文章的指引,也能完成三级等保测评。

PS:如果你的项目已经成型并上线。那在你整改时,有改变项目架构的风险,整改时请谨慎一些。项目也需要一个整体性的测试才去迭代上线。

所需准备

1.堡垒机
2.服务器(单个或多个)
3.客户端(单个或多个)
4.测评机构(一定要有认证的机构)
5.安全文档(保密协议,服务器授权书,管理流程等等文档)

堡垒机 :堡垒机作为登录服务器的入口,做了很多安全性的架构,很多等保测评机构也会直接点名需要堡垒机。
若你项目没有足够的人员维护服务器的安全性。那么购买堡垒机(云服务器的大厂商基本都有堡垒机,自行搜索)是个不错的解决方案,他能给你的服务器解决很多配置问题,无需你对服务器的安全性过多操心。
PS:如果你觉得可以搞定服务器(硬件)的安全性问题,可以抵御大部份的攻击,也可以选择不买堡垒机。

服务器
1.硬件服务器:这里只是指你的硬件服务器。如果有多个也需要一起整改。此类整改基本为固定的操作,Linux系统需要修改一些配置,对你项目的软件服务器影响较小,也比较简单,会在后面做说明。
2.业务服务器:这里是指你的业务服务器,包括数据库,一般都会有对外部的接口,所以需要解决一些非法访问,敏感数据传输,越权问题,数据安全问题等等。

客户端 :这里只是指你的项目是否有对外的客户端,有则一起整改。此类整改基于你的项目架构。由于客户端基本对外开放,所以敏感数据加密,传输加密,防暴力破解等为基础且必要的整改。

测评机构 :测评机构的收费不一,可根据自己情况选择,但一定要找到有政府正规认证的测评机构,根据他们的整改建议一点点修改,可以保证你一次通过。
当然,理论上也可以不请测评机构,如果你们项目组中有人有类似经验的人,或者有厉害的网安工程师给与你们整改建议,也可以自己整改。但有一点是,正式的测评一年只有一次机会,一次不通过需要等到第二年。所以对于没有过类似工作经验的,找测评机构会少走很多弯路。

安全文档 :一些需要规范化的文档,可能需要专人整理文档,这是一个必要且繁杂的工作,如果你请了测评机构。则他们会为你提供文档模板及文案。这也是他们需要帮你审核整改的内容之一。
所有文档都需要打印成纸质并盖公章,需要和你项目备案时的公章一样

服务器整改(硬件部分)

1.添加三员,且三权必须分离

服务器管理员,安全管理员,审计管理员。也就是至少添加这三个账号,需要不同的权限(即三权分离)。其他账号根据自己的业务而定。包括数据库也需要添加三员。

2.密码复杂度

 (1)密码90天更新一次,密码改为90天更改一次
//将9999改成90vim /etc/login.defs


(2)系统的登录密码需要配置密码复杂度(密码最小长度8位,其中包括2个大写字母、1个小写字母、4个数字、1个特殊字符;等保要求是最少8位字符,其中包括字母、数字、特殊字符)

//配置如图红框内
vim /etc/pam.d/system-auth

3.登录失败、超时处理

 (1)登录失败3次锁定账户5分钟,时间越久越好。登录超时5分钟自动退出。根据你的具体情况而定
//配置如图红框内
vim /etc/pam.d/system-auth


(2)登录超时5分钟(按秒计算)自动退出,根据业务情况设置

//配置如图红框内
vim /etc/profile

4.日志转存至日志审计

 服务器日志需要转存至日志审计设备中。若有堡垒机或者其他处理方式,可以不用此配置。只需要做一个异地(如服务器在贵阳,可以在上海的云服务器中储存日志)的日志增量备份和全量备份。
//服务器日志转存至日志审计设备中,如果你买了obs桶可以不配置此项
vim /etc/rsystem.conf

5.日志需要本机储存:
至少6个月

//将图中红框内weekly改成monthlyrotate 4 改成 rotate 6
vim /etc/logrotate.conf

6.限制IP登录:
根据具体情况,最好可以限制到某些IP段才能登录服务器。如公司wifi的IP段等。

7.杀毒软件安装:
建议最好为开源软件,linux推荐ClamAV 。

服务器整改(业务服务器)

1.数据库整改(以我的项目为例springboot+mybatis+pgsql)

(1)添加三员:同硬件服务器,数据库服务器也需要创建3个账号,并且分配不同权限(权限主要用于区分不同,可随意分配)

2.加密

注:如果你的项目中有MD5加密的方式,请换成需要密钥的对称加密,或非对称加密,或对MD5串进行二次加密

(1)敏感信息加密存储:如手机号,身份证等敏感信息,需要加密存入数据库中(PS:mybatis拦截器
本项目是基于Interceptor(自定义拦截器)来实现拦截加密。Java与数据库的数据交换基本都是基于实体类。所以用通过注解类标识需要加密字段的方式,进行字段加密处理。

先创建用于注解实体类的注解类。

//创建注解类,用于注解整个实体类。标识需要处理的类
import java.lang.annotation.*;
/*** 注解敏感信息类的注解* @author LeeMJ* @date 2021-9-3*/
@Inherited
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface SensitiveData {//可不写默认值
}

有了注解实体类的注解后,再创建用于注解字段的注解类。

//创建注解类,用于注解需要处理的字段。
import java.lang.annotation.*;
/*** 注解敏感信息类的注解* @author LeeMJ* @date 2021-9-3*/
@Inherited
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface SensitiveData {//可不写默认值
}

(参考)实体类注解例子

//创建注解类,用于注解需要处理的字段。
@SensitiveData
public class UserInfo {//个人账户信息表@SensitiveFieldprivate String phone;   //手机号@SensitiveFieldprivate String idcard;   //身份证private String user_nickname;   //用户昵称
}

接下来就是关键的 (加密)拦截器 部分,拦截查找是否有注解的加密字段。并进行加密操作存入数据库。

import com.fecred.bisouiya.entity.bo.SensitiveData;
import com.fecred.bisouiya.utils.AesUtils;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.PreparedStatement;
import java.util.Objects;
import java.util.Properties;/*** 数据库敏感信息加密* @author LeeMJ* @date 2021-9-3*/@Component
//拦截 ParameterHandler 的 setParameters 方法 动态设置参数
@Intercepts({@Signature(type = ParameterHandler.class,method = "setParameters",args = PreparedStatement.class),
})
@ConditionalOnProperty(value = "domain.encrypt", havingValue = "true")
public class EncryptInterceptor implements Interceptor {private static Logger log= LoggerFactory.getLogger(EncryptInterceptor.class);@Overridepublic Object intercept(Invocation invocation) throws Throwable {log.info("数据加密拦截器EncryptInterceptor");if (invocation.getTarget() instanceof ParameterHandler) {ParameterHandler parameterHandler = (ParameterHandler) invocation.getTarget();// 反射获取 实体类 参数对像Field parameterField = parameterHandler.getClass().getDeclaredField("parameterObject");parameterField.setAccessible(true);//获取实体类Object parameterObject = parameterField.get(parameterHandler);if (Objects.nonNull(parameterObject)) {Class<?> parameterObjectClass = parameterObject.getClass();SensitiveData encryptDecryptClass = AnnotationUtils.findAnnotation(parameterObjectClass, SensitiveData.class);//判断实体类中是否有@SensitiveData注解if (Objects.nonNull(encryptDecryptClass)) { //实体类Field[] declaredFields = parameterObjectClass.getDeclaredFields();try {for (Field field : declaredFields) {//取出所有被EncryptDecryptField注解的字段SensitiveField sensitiveField = field.getAnnotation(SensitiveField.class);//获取有@SensitiveField注解的元素if (!Objects.isNull(sensitiveField)) {field.setAccessible(true);Object object = field.get(parameterObject);//暂时只实现String类型的加密if (object instanceof String) {String value = (String) object;//加密  这里的Encrypt我使用自定义的AES加解密工具,可用你自己的加解密方法field.set(parameterObject, Encrypt(value));}}}} catch (Exception e) {log.error("数据加密失败:"+e.getMessage());}}}}return invocation.proceed();}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target,this);}@Overridepublic void setProperties(Properties properties) {}

然后是 (解密)拦截器 部分,配置同上

import com.fecred.bisouiya.entity.bo.SensitiveData;
import com.fecred.bisouiya.utils.AesUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;import java.sql.Statement;
import java.util.ArrayList;
import java.util.Objects;
import java.util.Properties;//拦截 ResultSetHandler 的 handleResultSets方法 动态设置返回值
@Intercepts({@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
})
@ConditionalOnProperty(value = "domain.decrypt", havingValue = "true")
@Component
public class DecryptInterceptor implements Interceptor {private static Logger log= LoggerFactory.getLogger(EncryptInterceptor.class);public Object intercept(Invocation invocation) throws Throwable {log.info("拦截器DecryptInterceptor");//获取结果集Object result = invocation.proceed();if (Objects.isNull(result)) {return null;}if (result instanceof ArrayList) {ArrayList resultList = (ArrayList) result;if (CollectionUtils.isNotEmpty(resultList) && needToDecrypt(resultList.get(0))) {for (int i = 0; i < resultList.size(); i++) {try {Class resultClass = result.getClass();Field[] declaredFields = resultClass.getDeclaredFields();for (Field field : declaredFields) {//取出所有被EncryptDecryptField注解的字段SensitiveField sensitiveField = field.getAnnotation(SensitiveField.class);if (!Objects.isNull(sensitiveField)) {field.setAccessible(true);Object object = field.get(result);//只支持String的解密if (object instanceof String) {String value = (String) object;//解密  这里的Decryp是我使用自定义的AES加解密工具,可用你自己的加解密方法field.set(result, Decrypt(value,key));}}}} catch (Exception e) {log.error("数据解密失败:"+e.getMessage());}}}} else {if (needToDecrypt(result)) {//同上相同的算法逻辑,可自行抽出方法体try {Class resultClass = result.getClass();Field[] declaredFields = resultClass.getDeclaredFields();for (Field field : declaredFields) {//取出所有被EncryptDecryptField注解的字段SensitiveField sensitiveField = field.getAnnotation(SensitiveField.class);if (!Objects.isNull(sensitiveField)) {field.setAccessible(true);Object object = field.get(result);//暂时只支持String的解if (object instanceof String) {String value = (String) object;//同上field.set(result, Decrypt(value));}}}} catch (Exception e) {log.error("数据解密失败:"+e.getMessage());}}}return result;}/*** 判断是否需要解密*/private boolean needToDecrypt(Object object) {if(!Objects.isNull(object)){Class<?> objectClass = object.getClass();SensitiveData encryptDecryptClass = AnnotationUtils.findAnnotation(objectClass, SensitiveData.class);if (Objects.nonNull(encryptDecryptClass)) {return true;}return false;}return false;}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {}
}

之后把拦截器写入配置文件中,做单独配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><!-- 数据库的其他配置,需要一起写入xml文件 --><settings><!-- 不区分大小写配置 --><setting name="mapUnderscoreToCamelCase" value="true" /><!-- 解决数据库null字段的显示 --><setting name="callSettersOnNulls" value="true" /> <!-- 懒加载配置 --><setting name="lazyLoadingEnabled" value="true" /> <!-- true表示如果对具有懒加载特性的对象的任意调用会导致这个对象的完整加载,false表示每种属性按照需要加载 --><setting name="aggressiveLazyLoading" value="false" /> </settings><plugins><!-- 加密拦截器 --><plugin interceptor="com.fecred.bisouiya.filter.DecryptInterceptor" /><!-- 解密拦截器 --><plugin interceptor="com.fecred.bisouiya.filter.EncryptInterceptor" /></plugins></configuration>

再把上方的xml配置文件配置进springboot的yml配置文件中

mybatis:# mybatis-config.xml 为上面的xml配置文件名称。建议放在yml的同目录下config-location: classpath:mybatis-config.xml# /mapper/*/*.xml 为我的mybatis的xml文件目录,多个用“,”隔开mapper-locations: classpath:/mapper/*/*.xml,classpath:/mapper/*.xml# com.xxx.xxx.entity 为我的实体类目录,可以不用包含当前包下的二级目录type-aliases-package: com.xxx.xxx.entity

数据库加密就到这,请根据你的具体情况自行选择解决方案。!!!

4.敏感信息过滤筛选

需要再前后端交互的时候,过滤掉一些敏感字段(如手机号,身份证等敏感信息)。
如果使用 http 的请求方式传参,必须加密传输所有字段。
如果使用 https 的请求方式,需要进行敏感信息过滤。或对敏感信息进行脱敏处理或加密处理。
由于本项目在整改的时候已经成型,需要脱敏的地方较多以及进度问题,只采用了所有web端接口参数对称加密的方式进行了处理。
过滤器 ,进行接口过滤,修改参数进行加密处理

1.由于需要对前端传输过来的参数进行修改,需要新建HttpServletRequestWrapper的继承类来操作入参

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.Enumeration;
import java.util.Map;public class ParameterRequestWrapper extends HttpServletRequestWrapper {private Map<String, String[]> parameterMap; // 所有参数的Map集合/*** ChangeRequestWrapper构造函数* @param request*/public ParameterRequestWrapper(HttpServletRequest request) {super(request);// 给参数集合赋值parameterMap = request.getParameterMap();}/*** 获取所有参数名** @return 返回所有参数名*/@Overridepublic Enumeration<String> getParameterNames() {Vector<String> vector = new Vector<String>(parameterMap.keySet());return vector.elements();}/*** 获取指定参数名的值,如果有重复的参数名,则返回第一个的值 接收一般变量 ,如text类型** @param name 指定参数名* @return 指定参数名的值*/@Overridepublic String getParameter(String name) {String result = super.getParameter(name);return result;}/*** 获取指定参数名的所有值的数组,如:checkbox的所有数据* 接收数组变量 ,如checkobx类型*/@Overridepublic String[] getParameterValues(String name) {return parameterMap.get(name);}@Overridepublic Map<String, String[]> getParameterMap() {return parameterMap;}public void setParameterMap(Map<String, String[]> parameterMap) {this.parameterMap = parameterMap;}}

2.再创建一个HttpServletResponseWrapper继承类用于处理服务器的返回结果

import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.*;public class WrapperedResponse extends HttpServletResponseWrapper {private ByteArrayOutputStream buffer = null;private ServletOutputStream out = null;private PrintWriter writer = null;public WrapperedResponse(HttpServletResponse resp) throws IOException {super(resp);// 真正存储数据的流buffer = new ByteArrayOutputStream();out = new WapperedOutputStream(buffer);writer = new PrintWriter(new OutputStreamWriter(buffer,this.getCharacterEncoding()));}/** 重载父类获取outputstream的方法 */@Overridepublic ServletOutputStream getOutputStream() throws IOException {return out;}/** 重载父类获取writer的方法 */@Overridepublic PrintWriter getWriter() throws UnsupportedEncodingException {return writer;}/** 重载父类获取flushBuffer的方法 */@Overridepublic void flushBuffer() throws IOException {if (out != null) {out.flush();}if (writer != null) {writer.flush();}}@Overridepublic void reset() {buffer.reset();}/** 将out、writer中的数据强制输出到WapperedResponse的buffer里面,否则取不到数据 */public byte[] getResponseData() throws IOException {flushBuffer();return buffer.toByteArray();}/** 内部类,对ServletOutputStream进行包装 */private class WapperedOutputStream extends ServletOutputStream {private ByteArrayOutputStream bos = null;public WapperedOutputStream(ByteArrayOutputStream stream)throws IOException {bos = stream;}@Overridepublic void write(int b) throws IOException {bos.write(b);}@Overridepublic void write(byte[] b) throws IOException {bos.write(b, 0, b.length);}@Overridepublic boolean isReady() {// TODO Auto-generated method stubreturn false;}@Overridepublic void setWriteListener(WriteListener writeListener) {// TODO Auto-generated method stub}}
}

3.加入过滤器Filter,做参数统一过滤处理

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.fecred.bisouiya.utils.AesUtils;
import com.fecred.bisouiya.utils.StringUtil;
import lombok.SneakyThrows;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** 解密过滤器* @author 李茂江* @Date 2021-12-16*/
@Order(Ordered.HIGHEST_PRECEDENCE)//控制过滤器的级别
public class DHEncryptFilter implements Filter {private static Logger log= LoggerFactory.getLogger(TokenFilter.class);//排除暴露链接public List<String> dhexposeUrls=new ArrayList<>();//过滤开关public boolean dhisOpen=false;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {//加载配置文件的配置,只对某些借口进行操作String tempExcludes=filterConfig.getInitParameter("dhExposeUrls");String tempEnabled=filterConfig.getInitParameter("dhIsOpen");if(!StringUtil.IsNullOrEmpty(tempExcludes)){String url[]=tempExcludes.split(",");for (int i=0;url!=null && i<url.length;i++){dhexposeUrls.add(url[i]);}}if(!StringUtil.IsNullOrEmpty(tempEnabled)){dhisOpen=Boolean.valueOf(tempEnabled);}}@SneakyThrows@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) servletRequest;HttpServletResponse resp = (HttpServletResponse) servletResponse;if(!handleExposeUrls(req,resp)){ParameterRequestWrapper parameterRequestWrapper = new ParameterRequestWrapper((HttpServletRequest)servletRequest);//由于本项目的传参方式为form-data类型,不好做接收处理,所以统一对所有参数进行加密后,让前端把参数写入encryptParams参数下,做取值后操作String encryptParams = parameterRequestWrapper.getParameter("encryptParams");Map<String,String[]> m = new HashMap<String,String[]>(parameterRequestWrapper.getParameterMap());//AesUtils.Decrypt为自定义的解密方法,请自行编写String de= AesUtils.Decrypt(encryptParams,null);Map paramMap = JSONObject.parseObject(de);Iterator<String> it = paramMap.keySet().iterator();while(it.hasNext()){String key = it.next();String[] IDList;IDList=new String[1];if(ObjectUtil.isEmpty(paramMap.get(key))){IDList[0]="";}else{IDList[0]= String.valueOf(paramMap.get(key));}m.put(key,IDList);}parameterRequestWrapper.setParameterMap(m);WrapperedResponse wrapResponse = new WrapperedResponse((HttpServletResponse) servletResponse);filterChain.doFilter(parameterRequestWrapper,wrapResponse);byte[] data = wrapResponse.getResponseData();String dataa=new String(data);log.info("原始返回数据: " + new String(data, "utf-8"));//AesUtils.Encrypt为自定义的加密方法,请自行编写String responseBodyMw = AesUtils.Encrypt(dataa,null);log.info("加密返回数据: " + responseBodyMw);writeResponse(servletResponse, responseBodyMw);}else{filterChain.doFilter(servletRequest,servletResponse);}}@Overridepublic void destroy() {}/*** 获取配置,判断是否需要过滤* @param request* @param response* @return*/private boolean handleExposeUrls(HttpServletRequest request, HttpServletResponse response){if(!dhisOpen){ return true; }if(dhexposeUrls==null || dhexposeUrls.size()<1){ return false; }String url=request.getServletPath();for (String pattern:dhexposeUrls){Pattern p=Pattern.compile("^"+pattern);Matcher m=p.matcher(url);if(m.find()){return true;}}return false;}/*** 写入响应体* @param response* @param responseString* @throws IOException*/private void writeResponse(ServletResponse response, String responseString)throws IOException {PrintWriter out = response.getWriter();out.print(responseString);out.flush();out.close();}
}

4.接着把过滤器加入配置

import com.fecred.bisouiya.filter.DHEncryptFilter;
import com.fecred.bisouiya.filter.TokenFilter;
import com.fecred.bisouiya.filter.XssFilter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;@Configuration
public class WebConfig {/*** 加解密过滤* @return*/@Value("${dhCheck.dhIsOpen}")private String dhIsOpen;@Value("${dhCheck.dhExposeUrls}")private String dhExposeUrls;@Value("${dhCheck.dhUrlPatterns}")private String dhUrlPatterns;@Beanpublic FilterRegistrationBean DHEncryptFilter(){FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean() ;filterRegistrationBean.setFilter(new DHEncryptFilter());filterRegistrationBean.setName("DHEncryptFilter");filterRegistrationBean.setOrder(1); //优先级 最高 1//匹配链接filterRegistrationBean.setUrlPatterns(Arrays.asList(dhUrlPatterns.split(",")));//自定义参数,传入自定义filterMap<String, String> initParameters = new HashMap<String, String>();initParameters.put("dhExposeUrls", dhExposeUrls);initParameters.put("dhIsOpen", dhIsOpen);filterRegistrationBean.setInitParameters(initParameters);return filterRegistrationBean;}/*** token过滤(自定的不用管,如果也需要,和加解密过滤器差不多的实现逻辑)* @return*/@Value("${tokenCheck.isOpen}")private String isOpen;@Value("${tokenCheck.exposeUrls}")private String exposeUrls;@Value("${tokenCheck.tokenUrlPatterns}")private String tokenUrlPatterns;@Beanpublic FilterRegistrationBean tokenFilter(){FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean() ;filterRegistrationBean.setFilter(new TokenFilter());filterRegistrationBean.setName("tokenFilter");filterRegistrationBean.setOrder(2); //优先级 第二//匹配链接filterRegistrationBean.setUrlPatterns(Arrays.asList(tokenUrlPatterns.split(",")));//自定义参数,传入自定义filterMap<String, String> initParameters = new HashMap<String, String>();initParameters.put("exposeUrls", exposeUrls);initParameters.put("isOpen", isOpen);filterRegistrationBean.setInitParameters(initParameters);return filterRegistrationBean;}/*** xss攻击过滤(自定的不用管)* @return*/@Value("${xss.enabled}")private String enabled;@Value("${xss.excludes}")private String excludes;@Value("${xss.urlPatterns}")private String urlPatterns;@Beanpublic FilterRegistrationBean xssFilter(){FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean() ;filterRegistrationBean.setFilter(new XssFilter());filterRegistrationBean.setName("xssFilter");filterRegistrationBean.setOrder(3); //优先级 第三//匹配链接filterRegistrationBean.setUrlPatterns(Arrays.asList(urlPatterns.split(",")));//自定义参数Map<String, String> initParameters = new HashMap<String, String>();initParameters.put("excludes", excludes);initParameters.put("enabled", enabled);filterRegistrationBean.setInitParameters(initParameters);return filterRegistrationBean;}
}

5.关于配置文件

#DH加解密过滤
dhCheck:# 过滤开关(false则为关闭过滤器,过滤器将失效)dhIsOpen: true# 暴露链接(不需要过滤的链接,多个用逗号分隔)dhExposeUrls: /PublicAPI/getKeys,/PublicAPI/geta#匹配链接(需要过滤的链接,一定会过滤)dhUrlPatterns: /DocAppointSpecial/*,/AppointCRoom/*,/ToolList/getAppointTimes

客户端整改

切记:某些整改在服务端已经处理过了,但是必须两端都有处理,只是服务端或只是客户端做了处理都不行!!!

1.敏感信息脱敏处理

敏感信息需要带星号处理,如: 手机号:13000000000 处理为 130****0000,身份证以及其他敏感数据也需要同样处理;
注:手机号、身份证、各种卡号等为必须脱敏处理;

2.参数验证

需要严格的参数验证,如字符串必须是数字等参数的验证,如手机号必须为手机号格式等;

3.密码规则

如有注册账号功能,且需设定密码规则:不少于12位,且必须包含,符号,数字,大写字母,小写字母其中3种;

三级等保测评,如何通过验收相关推荐

  1. 三级等保测评攻略来了,快快评论收藏哦

    今天给大家做了三级等保测评攻略,快快收藏起来哦!现在的人越来越注重安全,不管是人身安全.财产安全.还是网络安全,都是不可忽略的存在.企业更是需要注重信息安全,这也就出现了等级安全保护这项行业.虽然很多 ...

  2. 三级等保测评-服务器设置三权分立

    审计管理员     只读权限  赋予log目录只读权限 1.创建用户     useradd  shenjiadmin     passwd shenjiadmin 2.授权 vi /etc/sufo ...

  3. 22.扩展.等保测评相关实务

    1. 等保1.0 到等保2.0 等保1.0的概念:以1994年国务院颁布的147号令<计算机信息系统安全保护条例>为指导标准,以2008年发布的<GB/T22239-2008 信息安 ...

  4. 医院信息系统三级等保系统测评

    (一)项目清单 序号 名称 数量 1 HIS等保三级测评服务 1 2 PACS等保二级测评服务 1 (二)参数要求 1.测评对象 系统名称 安全等级 数量 HIS 三级 1 PACS 二级 1 2.测 ...

  5. 安全等保测评_等保二级和三级的区别

    安全等保测评_等保二级和三级的区别 等保测评即网络信息安全等级保护测评,是经公安部认证的具有资质的测评机构,依据国家信息安全等级保护规范规定,受有关单位委托,按照有关管理规范和技术标准,对信息系统安全 ...

  6. 等保测评三级——【安全物理环境】

    等保测评三级--[安全物理环境] 安全物理环境(十个测评单元) 一.物理位置选择 二.物理访问控制 三.防盗窃和防破坏 四.防雷击 五.防火 六.防水和防潮 七.防静电 八.温湿度控制 九.电力供应 ...

  7. centos 等保三级_等保测评主机安全:CentOS访问控制

    原标题:等保测评主机安全:CentOS访问控制 一.说明 权限控制在等保测评里仅仅说了要求,但是怎么落地却基本没写,怎么说呢,比较抽象. 所以,我觉得还是有必要了解一下centos系统大概有什么方法可 ...

  8. 等保测评2.0超详细解读,收藏这一篇就够了

    一.等级保护介绍 1.1什么是等级保护 网络安全等级保护是指对国家重要信息.法人和其他组织及公民的专有信息以及信息和存储.传输.处理这些信息的信息系统分等级实行安全保护,对信息系统中使用的信息安全产品 ...

  9. 等保测评之安全物理环境

    @[TOC](等保测评之安全通信网络) 一.物理位置选择 1.机房场地应选择在具有防震.防风和防雨等能力的建筑内(1-2)均为肯定) (1) 应核查所在建筑物是否具有建筑物抗震设防审批文档 一般都有审 ...

  10. 软件项目管理0713:三级等保的重要性

    软件项目管理0713:三级等保的重要性 作为项目经理一定要重视三级登保,如果是政府项目或者是大厂的项目,他们本身有等级比较高的制度或者是安全机构,会对于采购或者对接的系统进行安全评测,这样保证的软件的 ...

最新文章

  1. make 编译可执行
  2. c++ 读取访问权限冲突_关于Windows文件6项基础权限的一些设置!
  3. Python入门100题 | 第035题
  4. 使用IDEA编写Python程序,插件安装python插件,安装python SDK运行Python程序
  5. 解决Select2控件不能在jQuery UI Dialog中不能搜索的bug
  6. 语言五子棋无ai程序框图_2020输入法报告 如何选择更好的AI语音输入法?
  7. [ubuntu] ubuntu20.04 卸载 firefox 下载 chrome
  8. 也用 Log4Net 之走进Log4Net (四)
  9. win10修改命令行默认字体
  10. 推荐下载使用:功能强大的光盘刻录软件NERO 9.0中文版(最新官方原版+有效序列号)(转)...
  11. 最好的3个Windows电脑上的azw3阅读器
  12. 手机长度px值_px和厘米怎么换算?
  13. 【微信小程序/云开发bug解决方案合集】持续更新中(最新22-11-21)
  14. SpringBoot初试错误合集
  15. CH9101芯片应用—硬件设计指南
  16. MSE H265 支持调查
  17. 微服务架构实践心得小结
  18. 百度站长平台网站验证图文教程
  19. Surfer - 平滑地形
  20. 50mA带BASE极光耦型号TLP131,TLP630工作原理图

热门文章

  1. Android: 页面元素抓取工具Weditor
  2. RS485MODBUS RTU转PROFINET网关/PROFINET转MODBUS RTU网关将施耐德ATV610变频器接入西门子1500 PROFINET网络配置方法
  3. 关于用KMS的时候手欠把原装正版win11的激活卸载了怎么办
  4. 英特尔傲腾内存linux,英特尔一面优化傲腾可持续内存性能 一面不忘科普
  5. 软件设计与体系结构:设计过程
  6. sparksql 与flinksql 建表 与 连表记录
  7. Topaz Mask AI for mac(人工智能AI抠图软件) 最新版
  8. 一键导出微信所有聊天记录的小工具
  9. php 获取服务器端口,PHP获取当前服务器详细信息
  10. 程序员的自我修养 -- 读书笔记