• springboot项目配置ssl证书


    1.首先进入阿里云服务器,搜索ssl证书,免费申请,dns会自动解析该证书,所以不用设置

     2.下载tomcat和nginx服务器类型的证书

    3.将tomcat服务器类型的文件解压,打开,获得pfx文件,放入项目的resources文件中

    4.打开yml配置文件,进行SSL配置,并将http重定向到https

    1. custom:
    2. http:
    3. port: 8002 # 自定义http启动端口
    4. server: # https端口
    5. port: 8443
    6. ssl:
    7. key-store: classpath:8002091_suqiqaq.cn.pfx # pfk存放路径
    8. key-store-type: PKCS12 # tomcat服务器类型默认
    9. key-store-password: 1TFM7IpB # txt密码粘贴即可

      这里注意,server.port必须是https的端口,不然会出现https和http占用同一个端口

     5.添加配置类,让http重定向到https

    1. package com.guigusuqi.commonutils.config;
    2. import org.apache.catalina.Context;
    3. import org.apache.catalina.connector.Connector;
    4. import org.apache.tomcat.util.descriptor.web.SecurityCollection;
    5. import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
    6. import org.springframework.beans.factory.annotation.Value;
    7. import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
    8. import org.springframework.context.annotation.Bean;
    9. import org.springframework.context.annotation.Configuration;
    10. /**
    11. * https配置,将http请求全部转发到https
    12. */
    13. @Configuration
    14. public class HttpsConfig
    15. {
    16. @Value("${custom.http.port}")
    17. private Integer httpPort;
    18. @Value("${server.port}")
    19. private Integer httpsPort;
    20. @Bean
    21. public TomcatServletWebServerFactory servletContainer() {
    22. // 将http请求转换为https请求
    23. TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
    24. @Override
    25. protected void postProcessContext(Context context) {
    26. SecurityConstraint constraint = new SecurityConstraint();
    27. // 默认为NONE
    28. constraint.setUserConstraint("CONFIDENTIAL");
    29. SecurityCollection collection = new SecurityCollection();
    30. // 所有的东西都https
    31. collection.addPattern("/*");
    32. constraint.addCollection(collection);
    33. context.addConstraint(constraint);
    34. }
    35. };
    36. tomcat.addAdditionalTomcatConnectors(httpConnector());
    37. return tomcat;
    38. }
    39. /**
    40. * 强制将所有的http请求转发到https
    41. * @return httpConnector
    42. */
    43. @Bean
    44. public Connector httpConnector() {
    45. Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
    46. connector.setScheme("http");
    47. // connector监听的http端口号
    48. connector.setPort(httpPort);
    49. connector.setSecure(false);
    50. // 监听到http的端口号后转向到的https的端口号
    51. connector.setRedirectPort(httpsPort);
    52. return connector;
    53. }
    54. }

    如果我们不想强制所有的请求都重定向到https或者某些功能接口需要http的支持等等,我们也可以同时开启http协议和https协议。

    1. package cn.zlc.servicehttps.config;
    2. import org.apache.catalina.Context;
    3. import org.apache.catalina.connector.Connector;
    4. import org.apache.tomcat.util.descriptor.web.SecurityCollection;
    5. import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
    6. import org.springframework.beans.factory.annotation.Value;
    7. import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
    8. import org.springframework.context.annotation.Bean;
    9. import org.springframework.context.annotation.Configuration;
    10. @Configuration
    11. public class HttpsConfig {
    12. @Value("${server.port}")
    13. private Integer httpPort;
    14. @Bean
    15. public TomcatServletWebServerFactory servletContainer() {
    16. TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
    17. tomcat.addAdditionalTomcatConnectors(httpConnector());
    18. return tomcat;
    19. }
    20. @Bean
    21. public Connector httpConnector() {
    22. Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
    23. connector.setPort(httpPort);
    24. return connector;
    25. }
    26. }

    如果我们通过http端口请求的话,不会自动重定向到https端口,而且也不会提示需要TLS端口请求。而使用https请求的时候就会提示不安全,如果是放到服务器上访问https就正常了;

    6.将SpringBoot项目打为Jar包放置到Linux服务器下

    如果是宝塔 记得把--server.port=8002删掉,这里yaml配置的是8443端口,不然会覆盖掉yaml的配置,导致https和http又公用了一个端口

    访问后端接口文档成功 

    6. 安全组放行443端口,这个端口类似于http的80端口

    7.配置 nginx ,使用域名进行访问 

    将前端的http协议,重定向到https协议,https协议默认是443端口,所以还需要在443端口进行配置,这里需要配置ssl证书路径

    1. server
    2. {
    3. listen 80;
    4. server_name suqiqaq.cn;
    5. index index.php index.html index.htm default.php default.htm default.html;
    6. # ssl证书路径
    7. ssl_certificate /home/cert/8002091_suqiqaq.cn.pem;
    8. ssl_certificate_key /home/cert/8002091_suqiqaq.cn.key;
    9. root /home/hospital/app-api/dist;
    10. # $request_uri #包含请求参数的原始URI,不包含主机名
    11. # 如:”/foo/bar/arg”
    12. # $server_name #服务器名称
    13. # 将请求转成https,https协议默认是443端口,所以还需要在443端口进行配置
    14. return 301 https://$server_name$request_uri;
    15. }

    在nginx主配置文件中监听443端口,并将请求反向代理到https协议的8443端口

    注意,这里需要把前端项目路径加上,不然宝塔一直提示没有该站点

    1. server
    2. {
    3. listen 443 ssl;
    4. root /home/hospital/app-api/dist;
    5. index index.php index.html index.htm default.php default.htm default.html;
    6. server_name suqiqaq.cn;
    7. ssl_certificate /home/cert/8002091_suqiqaq.cn.pem;
    8. ssl_certificate_key /home/cert/8002091_suqiqaq.cn.key;
    9. location ^~ /hospitalApi/
    10. {
    11. proxy_pass https://127.0.0.1:8443/;
    12. # 这里是重点,如果上面的proxy_pass写成https的话这段是必须要配置的,不然只能访问页面,而页面调用端口不行
    13. proxy_ssl_certificate /home/cert/8002091_suqiqaq.cn.pem;
    14. proxy_ssl_certificate_key /home/cert/8002091_suqiqaq.cn.key;
    15. proxy_ssl_protocols TLSv1 TLSV1.1 TLSv1.2;
    16. proxy_ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    17. proxy_ssl_session_reuse on;
    18. proxy_redirect off;
    19. proxy_set_header Host $proxy_host;
    20. proxy_set_header X-Real-IP $remote_addr;
    21. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    22. proxy_set_header X-Nginx-Proxt true;
    23. proxy_set_header HTTP_X_FORWORDED_FOR $remote_addr;
    24. }
    25. }

    8.将前端的baseURL改为/hospitalApi,并把前端vue.config.js改为https协议,打包上线

    vue.config.js:

    1. 'use strict'
    2. const path = require('path')
    3. const defaultSettings = require('./src/settings.js')
    4. function resolve(dir) {
    5. return path.join(__dirname, dir)
    6. }
    7. const name = defaultSettings.title; // page title
    8. // If your port is set to 80,
    9. // use administrator privileges to execute the command line.
    10. // For example, Mac: sudo npm run
    11. // You can change the port by the following methods:
    12. // port = 9528 npm run dev OR npm run dev --port = 9528
    13. const port = 8080 // dev port
    14. // All configuration item explanations can be find in https://cli.vuejs.org/config/
    15. module.exports = {
    16. /**
    17. * You will need to set publicPath if you plan to deploy your site under a sub path,
    18. * for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,
    19. * then publicPath should be set to "/bar/".
    20. * In most cases please use '/' !!!
    21. * Detail: https://cli.vuejs.org/config/#publicpath
    22. */
    23. publicPath: '/',
    24. outputDir: 'dist',
    25. assetsDir: 'static',
    26. lintOnSave: process.env.NODE_ENV === 'development',
    27. productionSourceMap: false,
    28. devServer: {
    29. port: port,
    30. open: true,
    31. overlay: {
    32. warnings: false,
    33. errors: true
    34. },
    35. https: true // 开启https协议
    36. // before: require('./mock/mock-server.js')
    37. },
    38. configureWebpack: {
    39. // provide the app's title in webpack's name field, so that
    40. // it can be accessed in index.html to inject the correct title.
    41. name: name,
    42. resolve: {
    43. alias: {
    44. '@': resolve('src')
    45. }
    46. }
    47. },
    48. chainWebpack(config) {
    49. // it can improve the speed of the first screen, it is recommended to turn on preload
    50. config.plugin('preload').tap(() => [
    51. {
    52. rel: 'preload',
    53. // to ignore runtime.js
    54. // https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/cli-service/lib/config/app.js#L171
    55. fileBlacklist: [/\.map$/, /hot-update\.js$/, /runtime\..*\.js$/],
    56. include: 'initial'
    57. }
    58. ])
    59. // when there are many pages, it will cause too many meaningless requests
    60. config.plugins.delete('prefetch')
    61. // set svg-sprite-loader
    62. config.module
    63. .rule('svg')
    64. .exclude.add(resolve('src/icons'))
    65. .end()
    66. config.module
    67. .rule('icons')
    68. .test(/\.svg$/)
    69. .include.add(resolve('src/icons'))
    70. .end()
    71. .use('svg-sprite-loader')
    72. .loader('svg-sprite-loader')
    73. .options({
    74. symbolId: 'icon-[name]'
    75. })
    76. .end()
    77. config
    78. .when(process.env.NODE_ENV !== 'development',
    79. config => {
    80. config
    81. .plugin('ScriptExtHtmlWebpackPlugin')
    82. .after('html')
    83. .use('script-ext-html-webpack-plugin', [{
    84. // `runtime` must same as runtimeChunk name. default is `runtime`
    85. inline: /runtime\..*\.js$/
    86. }])
    87. .end()
    88. config
    89. .optimization.splitChunks({
    90. chunks: 'all',
    91. cacheGroups: {
    92. libs: {
    93. name: 'chunk-libs',
    94. test: /[\\/]node_modules[\\/]/,
    95. priority: 10,
    96. chunks: 'initial' // only package third parties that are initially dependent
    97. },
    98. elementUI: {
    99. name: 'chunk-elementUI', // split elementUI into a single package
    100. priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
    101. test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
    102. },
    103. commons: {
    104. name: 'chunk-commons',
    105. test: resolve('src/components'), // can customize your rules
    106. minChunks: 3, // minimum common number
    107. priority: 5,
    108. reuseExistingChunk: true
    109. }
    110. }
    111. })
    112. // https:// webpack.js.org/configuration/optimization/#optimizationruntimechunk
    113. config.optimization.runtimeChunk('single')
    114. }
    115. )
    116. }
    117. }

    request.js:

    1. import axios from 'axios'
    2. import { Message, MessageBox } from 'element-ui'
    3. import store from '../store'
    4. import { getToken } from '@/utils/auth'
    5. import {config} from "@vue/test-utils";
    6. // 创建axios实例
    7. const service = axios.create({
    8. // baseURL:process.env.VUE_APP_BASE_API,
    9. baseURL: "/hospitalApi", // api 的 base_url
    10. // baseURL: "http://suqiqaq.cn:8002", // api 的 base_url
    11. timeout: 10000000 // 请求超时时间
    12. })
    13. // http://suqiqaq.cn:8002/doc.html#/%E8%8B%8F%E4%B8%83/%E7%99%BB%E5%BD%95%E7%AE%A1%E7%90%86/loginUsingPOST
    14. // request拦截器
    15. service.interceptors.request.use(
    16. config => {
    17. config.headers['Content-Type'] = "application/json;charset=utf-8";
    18. if (store.getters.token) {
    19. config.headers['Authorization'] = getToken() // 让每个请求携带token
    20. }
    21. return config
    22. },
    23. error => {
    24. // Do something with request error
    25. console.log(error); // for debug
    26. Promise.reject(error)
    27. }
    28. )
    29. // response 拦截器
    30. service.interceptors.response.use(
    31. response => {
    32. /**
    33. * code为非200是抛错 可结合自己业务进行修改
    34. */
    35. const res = response.data;
    36. if (res.code !== 200)
    37. {
    38. Message({
    39. message: res.message,
    40. type: 'response error',
    41. duration: 5 * 1000
    42. });
    43. // 408:非法的token; 400:其他客户端登录了; 401:Token 过期了;
    44. if (res.code === 408 || res.code === 400 || res.code === 401)
    45. {
    46. if (getToken())
    47. {
    48. MessageBox.confirm(
    49. '你已被登出,可以取消继续留在该页面,或者重新登录',
    50. '确定登出',
    51. {
    52. confirmButtonText: '重新登录',
    53. cancelButtonText: '取消',
    54. type: 'warning',
    55. duration: 5 * 1000
    56. }
    57. ).then(() => {
    58. store.dispatch('FedLogOut').then(() => {
    59. location.reload() // 为了重新实例化vue-router对象 避免bug
    60. })
    61. })
    62. }
    63. }
    64. return Promise.reject('error')
    65. } else
    66. {
    67. return response.data
    68. }
    69. },
    70. error => {
    71. console.log('err' + error) // for debug
    72. Message({
    73. message: error.message,
    74. type: 'error',
    75. duration: 5 * 1000
    76. })
    77. return Promise.reject(error)
    78. }
    79. )
    80. export default service

    把前端项目上传到服务器之后即可,搞定!

  • 相关阅读:
    全景应用程序监控
    计算机毕业设计选题推荐-springboot 企业在线培训系统
    三菱PLC中通过变址寄存器V或Z实现简单跑马灯的程序示例及说明
    超详细spring boot笔记
    通用收藏管理器Koillection
    广州蓝景分享—「web前端素材」使用CSS动画效果(上)
    MFC使用MScomm32.ocx控件实现串口通信
    windows服务器环境下使用php调用com组件
    浅谈双指针技巧(三)利用快慢指针,查找链表中指定位置节点
    程序员周刊(第4期):程序员的财富观
  • 原文地址:https://blog.csdn.net/weixin_45974277/article/details/126064904