首页 > 其他分享 >秒懂HTTPS接口(实现篇)

秒懂HTTPS接口(实现篇)

时间:2023-04-05 10:07:04浏览次数:40  
标签:11 10 code return 实现 接口 12 HTTPS public

秒懂HTTPS接口(实现篇)_spring

HTTPS接口实现

下面我们来实践使用Java实现一个简单HTTPS接口示例

项目结构:


1. springbootdemo
2. ├─config 配置信息类
3. ├─controller 控制器类
4. ├─entity 实体类
5. ├─enums 枚举类
6. ├─exception 异常类
7. ├─handler 捕获类
8. ├─repository 数据访问类 
9. ├─util 工具类
10. ├─SpringbootdemoApplication 项目启动类
11. ├──resources 资源文件目录
12. │  ├─application.yml 全局配置文件
13. │  ├─banner.txt 项目启动banner
14. │  ├─tomcat.keystore SSL证书
15. │  ├─logback.xml 日志配置文件

主要特点:

  • Restful风格
  • 统一异常处理
  • SQL预处理

技术选型:

  • 核心框架:Spring Boot 2.1
  • 持久层框架:JPA 2.0
  • 日志管理:Logback
  • 数据库:MySQL 5.7
  • 插件:lombok

开发环境:

  • SUN JDK1.8
  • Maven 3.5.4

新建Spring Boot项目

这里使用的IDE是 IntelliJIDEA2018

秒懂HTTPS接口(实现篇)_spring_02

引包,配置pom.xml


1. <dependencies>
2.         <dependency>
3.             <groupId>org.springframework.boot</groupId>
4.             <artifactId>spring-boot-starter-data-jpa</artifactId>
5.         </dependency>
6.         <dependency>
7.             <groupId>org.springframework.boot</groupId>
8.             <artifactId>spring-boot-starter-data-rest</artifactId>
9.         </dependency>
10.         <!--引入MySQL驱动包-->
11.         <dependency>
12.             <groupId>mysql</groupId>
13.             <artifactId>mysql-connector-java</artifactId>
14.         </dependency>
15.         <dependency>
16.             <groupId>org.projectlombok</groupId>
17.             <artifactId>lombok</artifactId>
18.             <optional>true</optional>
19.         </dependency>
20.         <dependency>
21.             <groupId>org.springframework.boot</groupId>
22.             <artifactId>spring-boot-starter-test</artifactId>
23.             <scope>test</scope>
24.         </dependency>

编写Entity

编写Person实体bean,用于ORM对象关系映射,映射数据库表结构


1. /**
2.  * Person实体类
3.  */
4. 
5. @Entity
6. @Data
7. @Table(name = "person")
8. public class Person {
9.     //主键自增长
10.     @Id
11.     @GeneratedValue(strategy = GenerationType.IDENTITY)
12.     private Integer id;
13.     private String name;
14.     private Integer age;
15. }

创建一个接口PersonRepository,后续的控制器直接调用该接口继承自JpaRepository的方法,来实现和数据库交互


1. /**
2.  * 继承JpaRepository,实现与数据库交互(JPA支持自动生成一些基本CURD SQL语句)
3.  */
4. public interface PersonRepository extends JpaRepository<Person,Integer> {
5. 
6. }

统一异常处理

自定义异常

1. /**
2.  * 自定义异常类
3.  */
4. 
5. //RuntimeException继承Exception,spring只对继承RuntimeException的异常进行回滚
6. public class PersonException extends RuntimeException {
7.     private Integer code;
8. 
9.     public PersonException(ResultEnum resultEnum) {
10.         super(resultEnum.getMsg());
11.         this.code = code;
12.     }
13. 
14.     public Integer getCode() {
15.         return code;
16.     }
17. 
18.     public void setCode(Integer code) {
19.         this.code = code;
20.     }
21. }

捕获异常类

1. @ControllerAdvice
2. @Slf4j
3. public class ExceptionHandle {
4. 
5.     /**
6.      * 捕获异常类
7.      * @param e
8.      * @return
9.      */
10.     @ExceptionHandler(value = Exception.class)
11.     @ResponseBody
12.     public Result handle(Exception e){
13.         if (e instanceof PersonException){
14.             PersonException personException = (PersonException) e;
15.             return ResultUtil.error(personException.getCode(),personException.getMessage());
16.         }
17.         log.error("【系统错误】",e);
18.         return ResultUtil.error(-1,"未知错误");
19.     }
20. }

封装异常消息枚举


1. /**
2.  * 封装异常消息枚举类
3.  */
4. 
5. public enum ResultEnum {
6.     UNKONW_ERROR(-1, "未知错误"),
7.     SUCCESS(0, "成功");
8. 
9.     private Integer code;
10.     private String msg;
11. 
12.     ResultEnum(Integer code, String msg) {
13.         this.code = code;
14.         this.msg = msg;
15.     }
16. 
17.     public Integer getCode() {
18.         return code;
19.     }
20. 
21.     public String getMsg() {
22.         return msg;
23.     }
24. }

封装异常对象实体


1. /**
2.  * 封装异常对象(Http请求返回的最外层对象)
3.  * @param <T>
4.  */
5. 
6. @Data
7. public class Result<T> {
8.     //错误码
9.     private Integer code;
10.     //提示信息
11.     private String msg;
12.     private T date;
13. }

异常工具类


1. /**
2.  * 异常工具类
3.  */
4. public class ResultUtil {
5.     public static Result sucess(Object obj) {
6.         Result result = new Result();
7.         result.setCode(0);
8.         result.setMsg("sucess");
9.         result.setDate(obj);
10.         return result;
11.     }
12. 
13.     public static Result sucess() {
14.         Result result = new Result();
15.         result.setCode(0);
16.         result.setMsg("sucess");
17.         return result;
18.     }
19. 
20.     public static Result error(Integer code, String message) {
21.         Result result = new Result();
22.         result.setCode(code);
23.         result.setMsg(message);
24.         return result;
25.     }
26. }

创建RESTful API

风格设计

请求类型

请求路径

功能

Get

/person

获取人员列表

Post

/person

创建一个人员

创建Controller


1. /**
2.  * 控制器,处理Http/https请求(RESTful API)
3.  */
4. 
5. @RestController
6. public class PersonController {
7.     @Autowired
8.     PersonRepository personRepository;
9. 
10.     /**
11.      * 查询所有人员列表(Get方式)
12.      * @return
13.      */
14. 
15.     @GetMapping(value = "/person")
16.     private List<Person> personlist() {
17.         return personRepository.findAll();
18.     }
19. 
20.     /**
21.      * 添加人员 (Post方式)
22.      * @param person
23.      * @return
24.      */
25.     @PostMapping(value = "/person")
26.     public Result personAdd(HttpServletRequest request,@RequestBody Person person) {
27.         return ResultUtil.sucess(personRepository.save(person));
28.     }
29. }

使用SSL-HTTPS

Spring Boot中使用HTTPS步骤:

  1. 要有一个SSL证书,证书怎么获取呢?买(通过证书授权机构购买)或者自己生成(通过keytool生成)
  2. 启用HTTPS
  3. 将HTTP重定向到HTTPS(可选)

获取SSL证书

有两种方式可以获取到SSL证书:

  • 自己通过keytool生成;
  • 通过证书授权机构购买;

这里作为演示,采用keytool生成,实际项目中大部分采用的都是购买的方式。 那么怎么使用keytool生成呢? Keytool是Java提供的证书生成工具,如果配置了JAVA_HOME的,直接就可以在控制台进行生成了,这里演示使用的是Mac的终端窗口


1. 192:~ apple$ keytool -genkey -alias tomcat -keyalg RSA -keystore tomcat.keystore
2. 输入密钥库口令:  
3. 再次输入新口令: 
4. 您的名字与姓氏是什么?
5.   [Unknown]:  zuozewei
6. 您的组织单位名称是什么?
7.   [Unknown]:  7DGroup
8. 您的组织名称是什么?
9.   [Unknown]:  7D
10. 您所在的城市或区域名称是什么?
11.   [Unknown]:  Beijing
12. 您所在的省/市/自治区名称是什么?
13.   [Unknown]:  Beijing
14. 该单位的双字母国家/地区代码是什么?
15.   [Unknown]:  CN
16. CN=zuozewei, OU=7DGroup, O=7D, L=Beijing, ST=Beijing, C=CN是否正确?
17.   [否]:  y
18. 
19. 输入 <tomcat> 的密钥口令
20.     (如果和密钥库口令相同, 按回车):  
21. 再次输入新口令: 

查看生成的SSL证书信息


1. apple$ keytool -list -keystore tomcat.keystore 
2. 输入密钥库口令:  
3. 密钥库类型: jks
4. 密钥库提供方: SUN
5. 
6. 您的密钥库包含 1 个条目
7. 
8. tomcat, 2018-11-29, PrivateKeyEntry, 
9. 证书指纹 (SHA1): 2B:C5:FB:77:2C:5E:DC:5B:C5:E9:9F:06:27:7F:2E:A4:E4:9E:DF:8C

这里解释下命令的各个参数的含义:

  • genkey :生成key;
  • alias :key的别名;
  • dname:指定证书拥有者信息
  • storetype :密钥库的类型为JCEKS。常用的有JKS(默认),JCEKS(推荐),PKCS12,BKS,UBER。每个密钥库只可以是其中一种类型。
  • keyalg :DSA或RSA算法(当使用-genkeypair参数),DES或DESede或AES算法(当使用-genseckey参数);
  • keysize :密钥的长度为512至1024之间(64的倍数)
  • keystore :证书库的名称
  • validity : 指定创建的证书有效期多少天

dname的值详解:

  • CN(Common Name名字与姓氏)
  • OU(Organization Unit组织单位名称)
  • O(Organization组织名称)
  • L(Locality城市或区域名称)
  • ST(State州或省份名称)
  • C(Country国家名称)

这时候在当前目录下就会看到一个文件 tomcat.keystore,到这里SSL证书就有了。

启用HTTPS

默认情况下Spring Boot内嵌的Tomcat服务器会在8080端口启动HTTP服务,Spring Boot允许在全局配置文件中配置HTTP或HTTPS,但是不可同时配置,如果两个都启动,至少有一个要以编程的方式配置,Spring Boot官方文档建议在application配置文件中配置HTTPS,因为HTTPS比HTTP更复杂一些

在 application.yml中配置HTTPS,配置信息如下:


1. server:
2.   port: 443
3.   servlet:
4.     context-path: /springboot
5.   ssl:
6.     key-store: classpath:tomcat.keystore
7.     key-store-type: jks
8.     key-alias: tomcat
9.     key-store-password: zuozewei
10.     key-store-provider: SUN
11.     key-password: zuozewei
12.     enabled: true

注意:请将在上一步生成的证书放到 src/main/resources目录下。

将HTTP请求重定向到HTTPS

由于不能同时在application.l中同时配置两个connector,所以要以编程的方式配置HTTP Connector,然后重定向到HTTPS Connector

编写TomcatHttp配置类


1. @Configuration
2. public class TomcatHttpConfig {
3. 
4.     /**
5.      * 配置内置的Servlet容器工厂为Tomcat
6.      * @return
7.      */
8.     @Bean
9.     public ServletWebServerFactory servletContainer() {
10.         TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
11.             @Override
12.             protected void postProcessContext(Context context) {
13.                 SecurityConstraint securityConstraint = new SecurityConstraint();
14.                 securityConstraint.setUserConstraint("CONFIDENTIAL");
15.                 SecurityCollection collection = new SecurityCollection();
16.                 collection.addPattern("/*");
17.                 securityConstraint.addCollection(collection);
18.                 context.addConstraint(securityConstraint);
19.             }
20.         };
21.         //添加配置信息,主要是Http的配置信息
22.         tomcat.addAdditionalTomcatConnectors(redirectConnector());
23.         return tomcat;
24.     }
25. 
26.     /**
27.      * 配置一个Http连接信息
28.      * @return
29.      */
30.     private Connector redirectConnector() {
31.         Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
32.         connector.setScheme("http");
33.         connector.setPort(8088);
34.         connector.setSecure(false);
35.         connector.setRedirectPort(443);
36.         return connector;
37.     }
38. }

自定义启动标志

只需要在 src/main/resources路径下新建一个banner.txt文件,banner.txt中填写好需要打印的字符串内容即可。 一般情况下,我们会借助第三方工具帮忙转化内容,如: 

网站:http://www.network-science.de/ascii/ 将文字转化成字符串, 

网站:http://www.degraeve.com/img2txt.php 可以将图片转化成字符串。

配置日志配置文件

只需要在 src/main/resources路径下新建一个 logback.xml配置文件


1. <?xml version="1.0" encoding="UTF-8"?>
2. <configuration>
3.     <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
4.     <property name="FILE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{80} - %msg%n"/>
5.     <property name="LOG_PATH" value="${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}"/>
6.     <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
7.         <file>${LOG_PATH}/${LOG_FILE}</file>
8.         <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
9.             <fileNamePattern>${LOG_PATH}/${LOG_FILE}.%d{yyyy-MM-dd}</fileNamePattern>
10.         </rollingPolicy>
11.         <encoder charset="UTF-8">
12.             <pattern>${FILE_LOG_PATTERN}</pattern>
13.         </encoder>
14.     </appender>
15.     <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
16.         <encoder>
17.             <pattern>${FILE_LOG_PATTERN}</pattern>
18.         </encoder>
19.     </appender>
20.     <appender name="CRAWLER_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
21.         <file>${LOG_PATH}/event.log</file>
22.         <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
23.             <fileNamePattern>${LOG_PATH}/event.%d{yyyy-MM-dd}.log</fileNamePattern>
24.             <maxHistory>30</maxHistory>
25.         </rollingPolicy>
26.         <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
27.             <pattern>%msg%n</pattern>
28.         </encoder>
29.     </appender>
30.     <logger name="com.business.intelligence.util.CrawlerLogger" level="INFO" additivity="false">
31.         <appender-ref ref="CRAWLER_LOG"/>
32.     </logger>
33.     <root level="INFO">
34.         <appender-ref ref="STDOUT"/>
35.         <appender-ref ref="FILE"/>
36.     </root>
37. </configuration>

配置数据库配置

手动先创建 db_person数据库

1. spring:
2.   profiles:
3.     active: a
4.   datasource:
5.     driver-class-name: com.mysql.jdbc.Driver
6.     #手动创建db_person数据库
7.     url: jdbc:mysql://39.105.21.2:3306/db_person?useUnicode=true&characterEncoding=utf-8&useSSL=false
8.     username: zuozewei
9.     password: zuozewei
10. jpa:
11.   hibernate:
12.     ddl-auto: update
13.   show-sql: true

启动并测试

启动项目

秒懂HTTPS接口(实现篇)_HTTPS_03

通过浏览器输入:http://127.0.0.1:8088/springboot/person 

秒懂HTTPS接口(实现篇)_HTTPS_04

我们可以看到浏览器自动重定向到 https://127.0.0.1/springboot/person

点击浏览器上方的证书,我们可以看到使用的SSL证书信息 

秒懂HTTPS接口(实现篇)_tomcat_05

完整的项目结构

秒懂HTTPS接口(实现篇)_HTTPS_06


标签:11,10,code,return,实现,接口,12,HTTPS,public
From: https://blog.51cto.com/u_15181572/6170228

相关文章

  • 【fastweixin框架教程7】微信企业号自定义菜单接口开发
     下面这个类我对fastweixin框架的简单封装调用,大家可以参考,如果需要QYAPIConfigExt和MainServernSupport,请参考本教程以前几篇文章  应用可以在会话界面底部设置自定义菜单,菜单项可按需设定,并可为其设置响应动作。用户可以通过点击菜单项,收到你设定的消息。企业号支持自定义......
  • 使用Async和Await可以实现多任务顺序执行且不阻塞
    使用Async和Await可以实现多任务顺序执行且不阻塞//////////////////////对于async和await的使用方式、作用效果不怎么理解?没关系,初步看这篇就够了 结论同步还是异步,区别如下:同步:你使用 await 修饰符去调用一个异步(async)方法(是异步方法,不过是阻塞式的,可简单理解为同......
  • 今日总结-采用opencv库实现人脸识别
      实现效果如上经过opencv配置与调用opencv训练好的模板最终一晚上多次尝试实现了人脸识别。后续,会继续努力实现人脸对此与人脸关键点检测。#导入cv模块importcv2ascv#检测函数defface_detect_demo():gray=cv.cvtColor(img,cv.COLOR_BGR2GRAY)face_detec......
  • 手把手教你实现Android编译期注解
    一、编译期注解在开发中的重要性从早期令人惊艳的ButterKnife,到后来的以ARouter为首的各种路由框架,再到现在谷歌大力推行的Jetpack组件,越来越多的第三方框架都在使用编译期注解这门技术,可以说不管你是想要深入研究这些第三方框架的原理还是要成为一个Android高级开发工程师,编译期......
  • 一个简单SpringMVC的实现
    之前学习时候,是使用老师的自定义的一个SpringMVC模式,今天突然好奇,官方的SpringMVC架构咋弄,于是带着好奇的心去实现完成它其实这个模式也比较简单1:首先,我们创建一个maven,web的网页项目,JDK选择1.8版本   2:在创建完之后,鼠标右键点击main目录,同时选择java和resource包按回车......
  • 单向链表和双向链表的逆序的两种实现方式
    单向链表的逆序实现方式publicstaticclassNode{privateintval;privateNodenext;publicNode(intval){this.val=val;}}/**实现单向链表的第一种方式,只通过链表指针的重连来实现*/publicstaticNoderece......
  • 下拉列表的接口开发
    摘要:查询合并症的下拉列表其中涉及到单张表(TbComplication表)这个接口的设计思路:用户点击下拉列表框时,显示出来的合并症中的内容TbComplicationController@RestController@RequestMapping("/business/complication")publicclassTbComplicationControllerextendsBa......
  • 05-Go方法、接口、泛型
    1方法//方法1.是特殊的函数,可以自动传值--->对象(go中就是结构体)来调用,自动把对象(当前结构体的实例)传过来2.在func关键字和方法名中间加入了一个特殊的接收器类型接收器可以是结构体类型或者是非结构体类型接收器是可以在方法的内部访问的3.方......
  • C++实现AES加密
    参考https://zhuanlan.zhihu.com/p/567141666本人开发环境:vs2022,平台工具集vs2015(v140)要做到的如下图需要下载Cryptopp库https://github.com/weidai11/cryptopp打开默认工程,生成即可,选择cryptlib项目点击生成,产生头文件和lib文件实现代码:#include<Cryptopp/aes.h>#i......
  • Python——单元测试的实现
    摘要单元测试是用来对一个模块、一个函数或者一个类来进行正确性检验的测试工作。在软件开中的测试是很重要的一部分。python测试相关库unittest,内置库,模仿PyUnit写的,简洁易用,缺点是比较繁琐。nose,测试发现,发现并运行测试。pytest,笔者目前喜欢用这个,写起来很方便,并且很多知名开源项......