ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

spring boot

2021-10-27 14:03:17  阅读:174  来源: 互联网

标签:username spring xxx boot double new password public


1、配置文件application.properties加载顺序和优先级

  • 优先级:高 -> 低
    • ./config/
    • ./
    • classpath:/config/
    • classpath:

所有的文件都会被加载,加载配置文件的顺序从低优先级到高优先级,高优先级的内容会覆盖低优先级的内容,形成互补配置。

  • 常用配置
#Logger配置
logging.level.com.xxx= info
logging.file.path=./log

#数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
spring.datasource.username=xxx
spring.datasource.password=xxxxxx
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

#mybatis配置
mybatis.mapper-locations=classpath:mapper/*.xml
##开启驼峰命名
mybatis.global-config.column-underline=true
mybatis.configuration.map-underscore-to-camel-case=true
#控制台打印sql语句
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

#上传文件大小限制
##单个文件大小
spring.servlet.multipart.max-file-size=100MB
##总上传数据大小
spring.servlet.multipart.max-request-size=100MB

2、项目启动时初始化资源:CommandLineRunner或ApplicationRunner

@Component//标识为Bean
@Order(1)//如果有多个runner可以指定一些顺序
public class InitRunner implements ApplicationRunner {
I
    @Autowired
    private ConfigurableApplicationContext applicationContext;

    @Override
    public void run(ApplicationArguments args) {
        
        //初始化逻辑代码
        
        //初始化失败时停止启动
        applicationContext.close();
    }
}

3、static变量使用@Value从配置文件取值

server.seckey=turtledove
server.maps={key1:'value1', key2:'value2', key3:'value3'}
@Component
public class Host {

    public static String SECKEY;
    public static Map<String, String> xxxMap = new HashMap<>();

    @Value("${server.seckey}")
    public void setSeckey(String seckey) {
        SECKEY = seckey;
    }

    @Value("#{${server.maps}}")
    public void setUrlMap(Map<String, String> urlMap) {
        Host.urlMap = urlMap;
    }
}

4、multipartFile.transferTo()路径问题

分析下面源码,multipartFile.transferTo()首先会执行一个write方法,这个write方法会判断传入参数的路径是否是相对路径,如果是相对路径,则把它拼接成绝对路径。

  • 源码
public class StandardMultipartHttpServletRequest extends AbstractMultipartHttpServletRequest {
 
    public void transferTo(File dest) throws IOException, IllegalStateException {
            this.part.write(dest.getPath());
            if (dest.isAbsolute() && !dest.exists()) {
                FileCopyUtils.copy(this.part.getInputStream(), Files.newOutputStream(dest.toPath()));
            }
        }
}
public class ApplicationPart implements Part {
     
    public void write(String fileName) throws IOException {
            File file = new File(fileName);
            if (!file.isAbsolute()) {
                file = new File(this.location, fileName);
            }

            try {
                this.fileItem.write(file);
            } catch (Exception var4) {
                throw new IOException(var4);
            }
        }
}
  • 使用
//相对路径
multipartFile.transferTo(new File("./xxx/xxx"));

//绝对路径
//因为windows的绝对路径以盘符开始如"C:/xxx/xxx",linux的绝对路径以斜杠开始如"/xxx/xxx",为避免服务从windows环境部署到linux环境时出问题,推荐使用第三种
multipartFile.transferTo(new File("C:/xxx/xxx"));//windows
multipartFile.transferTo(new File("/xxx/xxx"));//linux
multipartFile.transferTo(new File("./xxx/xxx").getAbsoluteFile());//推荐

5、Interceptor 用法

  • 自定义拦截器
@Component
public class CheckUserTokenInterceptor implements HandlerInterceptor {

      @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}
  • 配置拦截器
@Configuration
public class WebConfigurer implements WebMvcConfigurer {

    @Autowired
    private CheckUserTokenInterceptor checkUserTokenInterceptor;
    
    @Autowired
    private XxxInterceptor xxxInterceptor;

    /**
     * 注册拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(checkUserTokenInterceptor).addPathPatterns("/xxx/**").addPathPatterns("/xxx/**");
        registry.addInterceptor(xxxInterceptor).addPathPatterns("/xxx/**").addPathPatterns("/xxx/**");
    }
}
  • 自定义返回
/**
 * 自定义响应数据
 */
public void setResponseBody(HttpServletResponse response, Result result) {
    response.setCharacterEncoding("UTF-8");
    response.setContentType("application/json");
    try (PrintWriter responseWriter = response.getWriter()) {
        responseWriter.print(JSON.toJSONString(result));
    } catch (IOException e) {
        log.error("response.getWriter()异常", e);
    }
}

6、服务调用脚本Runtime.getRuntime().exec(cmdString);

  • 不成熟demo
    public static boolean exec(String command) throws IOException, InterruptedException {

        //执行脚本
        Process exec = Runtime.getRuntime().exec(command);

        AtomicBoolean error = new AtomicBoolean(false);

        //新建线程记录错误信息,避免阻塞记录
        new Thread(() -> {
            BufferedReader errorReader = new BufferedReader(new InputStreamReader(exec.getErrorStream()));
            errorReader.lines().forEach(line -> {
                log.debug("bash error: {}", line);
                error.set(true);
            });
        }).start();

        //记录一般信息
        BufferedReader infoReader = new BufferedReader(new InputStreamReader(exec.getInputStream()));
        String line;
        while ((line = infoReader.readLine()) != null) {
            log.debug("bash info: {}", line);
        }

        exec.waitFor();
        return exec.exitValue() == 0 && !error.get();

    }

7、注解+AOP

  • @Aspect

  • @Pointcut:声明一个切入点

    匹配service中所有方法:@Pointcut("execution(* com.example.demo.service.*(..))")

    第一个*代表任意修饰符及任意返回值类型,第二个*代表任意方法,..匹配任意数量任意类型的参数,若目标类与该切面在同一个包中,可以省略包名。

    例如:

    //匹配XxxServiceImpl类中的所有公有方法
    @Pointcut("execution public * com.example.demo.service.XxxService.*(..)")
    
    //匹配XxxServiceImpl类中返回值类型为double类型的所有公有方法
    @Pointcut("execution public double com.example.demo.service.XxxService.*(..)")
    
    //匹配XxxServiceImpl类中第一个参数为double类型,后面不管有无参数的所有公有方法,并且该方法的返回值类型为double类型
    @Pointcut("execution public double com.example.demo.service.XxxService.*(double, ..)")
    
    //匹配XxxServiceImpl类中参数类型为double,double类型的,并且返回值类型也为double类型的所有公有方法
    @Pointcut("execution public double com.example.demo.service.XxxService.*(double, double)")s
    
    
  • @Around:环绕;@Before:前置

  • 用例:

    • 定义一个注解
    package com.example.demo.common.aspectj;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target({ElementType.METHOD, ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Log {
        String value() default "";
    }
    
    • 配置切入点
    @Aspect
    @Service
    public class LogAspect {
    
        @Pointcut("@annotation(com.example.demo.common.aspectj.Log)")
        public void pointCut() {
        }
    
        @Around("pointCut()")
        public Object around(ProceedingJoinPoint proceedingJoinPoint) {
            
            //前置逻辑
            
            Object obj = proceedingJoinPoint.proceed()
                
            //后置逻辑
                
            return obj;
    
        }
    }
    
    • 在需要切入的地方加上注解@Log即可切入

8、MD5

  1. 文件校验

    String md5_1 DigestUtils.md5DigestAsHex(new FileInputStream(path1));
    String md5_2 DigestUtils.md5DigestAsHex(new FileInputStream(path2));
    if (md5_1.equals(md5_2)){
        System.out.println("两文件相同");
    }else {
        System.out.println("两文件不同");
    }
    
  2. 密码校验

9、线程锁Lock lock = new ReentrantLock()

10、 Fastjson

  • demo

    //JSON.toJSONString(object)  将 object 转换换为  JSON  对象
    //JSON.parseObject() 将 JSON 字符串转换为 Java 对象
    Person person = new Person(20, "turtledove", new Date());
    String jsonString = JSON.toJSONString(person);
    Person newPerson = JSON.parseObject(jsonString, Person.class);
    //JSONArray
    JSONObject data = jsonObject.getJSONArray("data").getJSONObject(0);
    

11、Apache HttpClient

  • demo

    public static JSONObject postRequest(Object requestParams, String url) throws IOException {
        //请求参数json格式化
        String paramsJson = JSON.toJSONString(requestParams);
        //请求配置
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setEntity(new StringEntity(JSON.toJSONString(requestParams), "utf-8"));
        httpPost.setConfig(RequestConfig.custom().setConnectTimeout(2000).setSocketTimeout(2000).build());
        //执行请求
        CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
        //响应结果json格式化
        return JSONObject.parseObject(EntityUtils.toString(httpResponse.getEntity()));
    }
    

12、SQL注入

  • 攻击实例

    <select id="getUserLoginInfo" resultType="map">
        SELECT
            `username`,
            `password`
        FROM
            `user_table`
        WHERE
            `username` = ${username} AND `password` = ${password}
    </select>
    
    -- 正常情况下
    SELECT `username`, `password` FROM `user_table` WHERE `username` = 'username' AND `password` = 'password';
    
    -- sql注入1:当 username = "' or 1 = 1 -- "
    SELECT `username`, `password` FROM `user_table` WHERE `username` = '' or 1 = 1 -- ' AND `password` = 'password';
    
    -- sql注入2:当 username = "'; DROP DATABASE (DB Name) -- "
    SELECT `username`, `password` FROM `user_table` WHERE `username` = ''; DROP DATABASE (DB Name) -- ' AND `password` = 'password';
    
  • 分析SQL语句:
    --条件后面username=”or 1=1 用户名等于 ” 或1=1 那么这个条件一定会成功;
    
    --然后后面加两个-,这意味着注释,它将后面的语句注释,让他们不起作用,这样语句永远都--能正确执行,用户轻易骗过系统,获取合法身份。
    
  • 分析SQL

    • 条件后面username=”or 1=1 用户名等于 ” 或1=1 那么这个条件一定会成功;

    • 然后后面加两个-,这意味着注释,它将后面的语句注释,让他们不起作用,这样语句永远都--能正确执行,用户轻易骗过系统,获取合法身份。

  • 预防sql注入(mybatis)ti

    • 使用预编译语句:即尽量使用#{value}。

    若不得不使用“${xxx}”这样的参数,要手工地做好过滤工作,来防止SQL注入攻击。

    • 过滤特殊符号:对于无法确定固定格式的变量,一定要进行特殊符号过滤或转义处理。

    • 一次只执行一条sql语句:mybatis jdbc 默认 allowMultiQueries=false,非必要不修改。

    • 使用特定的用户账号,权限限制住。不要使用root用户。

13、Mybatis 动态SQL

  • where、if

    <select id="findActiveBlogLike" resultType="Blog">
      SELECT * FROM BLOG
      <where>
        <if test="author != null and author.name != null">
            AND author_name like #{author.name}
        </if>
      </where>
    </select>
    
  • foreach

    <foreach item="item" index="index" collection="list" open="(" separator="," close=")">
          #{item}
    </foreach>
    
  • choose、when、otherwise

    <select id="findActiveBlogLike" resultType="Blog">
      SELECT * FROM BLOG WHERE state = ‘ACTIVE’
      <choose>
        <when test="title != null">
          AND title like #{title}
        </when>
        <when test="author != null and author.name != null">
          AND author_name like #{author.name}
        </when>
        <otherwise>
          AND featured = 1
        </otherwise>
      </choose>
    </select>
    

标签:username,spring,xxx,boot,double,new,password,public
来源: https://www.cnblogs.com/littleturtledove/p/15469983.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有