web程序安全策略

web安全策略-java初级

拦截器

	该拦截器实现HandlerInterceptor接口,可根据业务重写方法实现请求拦截,这里我的代码采用的是对一个自定义
	请求头拦截
	
	preHandle:在服务层处理之前被调用,一般用户鉴权,token验证,uri或者ip拦截
	postHandle:服务层调用之后,返回视图之前被调用
	afterCompletion:在DispatcherServlet完全处理完请求后被调用
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author DKH
 */
public class AuthInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return request.getHeader("reqid") != null && request.getHeader("reqid").equals("dkh");
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }

}
需要将拦截器注册到容器中,并设置跨域
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig implements WebMvcConfigurer {
        @Bean
        public CorsFilter corsFilter() {
            //添加 CORS配置信息
            CorsConfiguration config = new CorsConfiguration();
            //放行哪些原始域
            config.addAllowedOriginPattern("*");
            //是否发送 Cookie
            config.setAllowCredentials(true);
            //放行哪些请求方式
            config.addAllowedMethod("*");
            //放行哪些原始请求头部信息
            config.addAllowedHeader("*");
            //暴露哪些头部信息
            config.addExposedHeader("*");
            //2. 添加映射路径
            UrlBasedCorsConfigurationSource corsConfigurationSource = 
            new UrlBasedCorsConfigurationSource();
            corsConfigurationSource.registerCorsConfiguration("/**",config);
            //3. 返回新的CorsFilter
            return new CorsFilter(corsConfigurationSource);
        }
        @Bean
        public AuthInterceptor initAuthInterceptor(){
            return new AuthInterceptor();
        }

        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(initAuthInterceptor()).addPathPatterns("/**");
        }

}

数据加密

在进行接口数据之前,前后端应进行商讨采用何种加密方式、加密密钥、解密规则
这里博主采用AES/ECB/PKCS5Padding加密规则
   //密钥 (需要前端和后端保持一致)
   private static final String KEY = "xxxxxxxxxxxxxxx";
   //算法
   private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";

   /**
    * base 64 encode
    */
   public static String base64Encode(byte[] bytes){
       return Base64.encodeBase64String(bytes);
   }
   /**
    * aes加密
    */
   public static String aesEncrypt(String content) {
       try {
           return aesEncrypt(content, KEY);
       } catch (Exception e) {
           e.printStackTrace();
           return "";
       }
   }
   /**
    * AES加密
    */
   public static byte[] aesEncryptToBytes(String content, String encryptKey)throws Exception
   {
       KeyGenerator kgen = KeyGenerator.getInstance("AES");
       kgen.init(128);
       Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
       cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));
       return cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
   }


   /**
    * AES加密为base 64 code
    */
   public static String aesEncrypt(String content, String encryptKey) throws Exception {
       return base64Encode(aesEncryptToBytes(content, encryptKey));
   }


前端解密
	/**
	 * 解密
	 */
	export function decrypt(word){
	  const key = CryptoJS.enc.Utf8.parse("xxxxxxxxxxxxxxx");
	  const decrypt = CryptoJS.AES.decrypt(word, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
	  return CryptoJS.enc.Utf8.stringify(decrypt).toString();
	}

请求限制

针对恶意请求的ip进行封禁,这里使用的是自定义注解并结合AOP,将用户的请求ip和uri存入内存,并设置过期时间
也可以使用redis进行缓存处理
import java.lang.annotation.*;

/**
 * @author DKH
 */

@Documented
@Target(ElementType.METHOD) // 说明该注解只能放在方法上面
@Retention(RetentionPolicy.RUNTIME)
    public @interface RestrictionRequest {
        long time() default 3000; // 限制时间 单位:毫秒
        int count() default 3; // 允许请求的次数
}
AOP
import com.dkh.common.annotation.RestrictionRequest;
import com.dkh.entity.AjaxResult;
import net.jodah.expiringmap.ExpirationPolicy;
import net.jodah.expiringmap.ExpiringMap;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * @author DKH
 */
@Aspect
@Component
public class RestrictionRequestAspect {

    private static ConcurrentHashMap<String, ExpiringMap<String, Integer>> book = new ConcurrentHashMap<>();


    @Pointcut("@annotation(RestrictionRequest)")
    public void excudeService(RestrictionRequest limitRequest) {

    }

    @Around("excudeService(RestrictionRequest)")
    public Object doAround(ProceedingJoinPoint pjp, RestrictionRequest limitRequest) throws Throwable {
        // 获得request对象
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        System.out.println("url="+request.getRequestURL()+";User-Agent="+request.getHeader("User-Agent"));
        ExpiringMap<String, Integer> uc = book.getOrDefault(request.getRequestURI(), ExpiringMap.builder().variableExpiration().build());
        Integer uCount = uc.getOrDefault(request.getHeader("User-Agent"), 0);
        // 超过次数,不执行目标方法
        if (uCount >= limitRequest.count()) {
            return AjaxResult.success("接口访问过多!");
            // 第一次请求时,设置有效时间
        } else if (uCount == 0){
            uc.put(request.getRemoteAddr(), uCount + 1, ExpirationPolicy.CREATED, limitRequest.time(), TimeUnit.MILLISECONDS);
        } else { // 未超过次数, 记录加一
            uc.put(request.getRemoteAddr(), uCount + 1);
        }
        book.put(request.getRequestURI(), uc);
        return pjp.proceed();
    }


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

do{a++b++}while(a&b)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值