mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-31 22:18:07 +08:00
feat: 网站支持设置 HTTPS 端口 (#6056)
This commit is contained in:
parent
2f34e1727f
commit
3d2d4318c7
@ -145,6 +145,7 @@ type WebsiteHTTPSOp struct {
|
|||||||
SSLProtocol []string `json:"SSLProtocol"`
|
SSLProtocol []string `json:"SSLProtocol"`
|
||||||
Algorithm string `json:"algorithm"`
|
Algorithm string `json:"algorithm"`
|
||||||
Hsts bool `json:"hsts"`
|
Hsts bool `json:"hsts"`
|
||||||
|
HttpsPort int `json:"httpsPort"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebsiteNginxUpdate struct {
|
type WebsiteNginxUpdate struct {
|
||||||
|
@ -59,6 +59,7 @@ type WebsiteHTTPS struct {
|
|||||||
SSLProtocol []string `json:"SSLProtocol"`
|
SSLProtocol []string `json:"SSLProtocol"`
|
||||||
Algorithm string `json:"algorithm"`
|
Algorithm string `json:"algorithm"`
|
||||||
Hsts bool `json:"hsts"`
|
Hsts bool `json:"hsts"`
|
||||||
|
HttpsPort int `json:"httpsPort"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebsiteLog struct {
|
type WebsiteLog struct {
|
||||||
|
@ -28,6 +28,8 @@ type Website struct {
|
|||||||
AppInstallID uint `gorm:"type:integer" json:"appInstallId"`
|
AppInstallID uint `gorm:"type:integer" json:"appInstallId"`
|
||||||
FtpID uint `gorm:"type:integer" json:"ftpId"`
|
FtpID uint `gorm:"type:integer" json:"ftpId"`
|
||||||
|
|
||||||
|
HttpsPort int `json:"httpsPort"`
|
||||||
|
|
||||||
User string `gorm:"type:varchar;" json:"user"`
|
User string `gorm:"type:varchar;" json:"user"`
|
||||||
Group string `gorm:"type:varchar;" json:"group"`
|
Group string `gorm:"type:varchar;" json:"group"`
|
||||||
|
|
||||||
|
@ -225,6 +225,7 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error)
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defaultHttpPort := nginxInstall.HttpPort
|
defaultHttpPort := nginxInstall.HttpPort
|
||||||
|
defaultHttpsPort := nginxInstall.HttpsPort
|
||||||
|
|
||||||
var (
|
var (
|
||||||
otherDomains []model.WebsiteDomain
|
otherDomains []model.WebsiteDomain
|
||||||
@ -239,6 +240,9 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error)
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
domains = append(domains, otherDomains...)
|
domains = append(domains, otherDomains...)
|
||||||
|
if len(domains) == 1 && domains[0].Port != defaultHttpPort {
|
||||||
|
defaultHttpsPort = domains[0].Port
|
||||||
|
}
|
||||||
|
|
||||||
defaultDate, _ := time.Parse(constant.DateLayout, constant.DefaultDate)
|
defaultDate, _ := time.Parse(constant.DateLayout, constant.DefaultDate)
|
||||||
website := &model.Website{
|
website := &model.Website{
|
||||||
@ -255,6 +259,7 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error)
|
|||||||
AccessLog: true,
|
AccessLog: true,
|
||||||
ErrorLog: true,
|
ErrorLog: true,
|
||||||
IPV6: create.IPV6,
|
IPV6: create.IPV6,
|
||||||
|
HttpsPort: defaultHttpsPort,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -459,8 +464,9 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error)
|
|||||||
SSLProtocol: []string{"TLSv1.3", "TLSv1.2", "TLSv1.1", "TLSv1"},
|
SSLProtocol: []string{"TLSv1.3", "TLSv1.2", "TLSv1.1", "TLSv1"},
|
||||||
Algorithm: "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:!aNULL:!eNULL:!EXPORT:!DSS:!DES:!RC4:!3DES:!MD5:!PSK:!KRB5:!SRP:!CAMELLIA:!SEED",
|
Algorithm: "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:!aNULL:!eNULL:!EXPORT:!DSS:!DES:!RC4:!3DES:!MD5:!PSK:!KRB5:!SRP:!CAMELLIA:!SEED",
|
||||||
Hsts: true,
|
Hsts: true,
|
||||||
|
HttpsPort: website.HttpsPort,
|
||||||
}
|
}
|
||||||
if err = applySSL(*website, *websiteModel, appSSLReq); err != nil {
|
if err = applySSL(website, *websiteModel, appSSLReq); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = websiteRepo.Save(context.Background(), website); err != nil {
|
if err = websiteRepo.Save(context.Background(), website); err != nil {
|
||||||
@ -863,6 +869,7 @@ func (w WebsiteService) GetWebsiteHTTPS(websiteId uint) (response.WebsiteHTTPS,
|
|||||||
return response.WebsiteHTTPS{}, err
|
return response.WebsiteHTTPS{}, err
|
||||||
}
|
}
|
||||||
var res response.WebsiteHTTPS
|
var res response.WebsiteHTTPS
|
||||||
|
res.HttpsPort = website.HttpsPort
|
||||||
if website.WebsiteSSLID == 0 {
|
if website.WebsiteSSLID == 0 {
|
||||||
res.Enable = false
|
res.Enable = false
|
||||||
return res, nil
|
return res, nil
|
||||||
@ -918,9 +925,12 @@ func (w WebsiteService) OpWebsiteHTTPS(ctx context.Context, req request.WebsiteH
|
|||||||
if !req.Enable {
|
if !req.Enable {
|
||||||
website.Protocol = constant.ProtocolHTTP
|
website.Protocol = constant.ProtocolHTTP
|
||||||
website.WebsiteSSLID = 0
|
website.WebsiteSSLID = 0
|
||||||
_, httpsPort, err := getAppInstallPort(constant.AppOpenresty)
|
httpsPort := website.HttpsPort
|
||||||
if err != nil {
|
if httpsPort == 0 {
|
||||||
return nil, err
|
_, httpsPort, err = getAppInstallPort(constant.AppOpenresty)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
httpsPortStr := strconv.Itoa(httpsPort)
|
httpsPortStr := strconv.Itoa(httpsPort)
|
||||||
if err := deleteListenAndServerName(website, []string{httpsPortStr, "[::]:" + httpsPortStr}, []string{}); err != nil {
|
if err := deleteListenAndServerName(website, []string{httpsPortStr, "[::]:" + httpsPortStr}, []string{}); err != nil {
|
||||||
@ -1025,7 +1035,7 @@ func (w WebsiteService) OpWebsiteHTTPS(ctx context.Context, req request.WebsiteH
|
|||||||
}
|
}
|
||||||
|
|
||||||
website.Protocol = constant.ProtocolHTTPS
|
website.Protocol = constant.ProtocolHTTPS
|
||||||
if err := applySSL(website, websiteSSL, req); err != nil {
|
if err := applySSL(&website, websiteSSL, req); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
website.HttpConfig = req.HttpConfig
|
website.HttpConfig = req.HttpConfig
|
||||||
|
@ -568,8 +568,8 @@ func createPemFile(website model.Website, websiteSSL model.WebsiteSSL) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func applySSL(website model.Website, websiteSSL model.WebsiteSSL, req request.WebsiteHTTPSOp) error {
|
func applySSL(website *model.Website, websiteSSL model.WebsiteSSL, req request.WebsiteHTTPSOp) error {
|
||||||
nginxFull, err := getNginxFull(&website)
|
nginxFull, err := getNginxFull(website)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -587,11 +587,15 @@ func applySSL(website model.Website, websiteSSL model.WebsiteSSL, req request.We
|
|||||||
server := config.FindServers()[0]
|
server := config.FindServers()[0]
|
||||||
|
|
||||||
httpPort := strconv.Itoa(nginxFull.Install.HttpPort)
|
httpPort := strconv.Itoa(nginxFull.Install.HttpPort)
|
||||||
httpsPort := strconv.Itoa(nginxFull.Install.HttpsPort)
|
httpsPort := nginxFull.Install.HttpsPort
|
||||||
|
if req.HttpsPort > 0 {
|
||||||
|
httpsPort = req.HttpsPort
|
||||||
|
}
|
||||||
|
website.HttpsPort = httpsPort
|
||||||
httpPortIPV6 := "[::]:" + httpPort
|
httpPortIPV6 := "[::]:" + httpPort
|
||||||
httpsPortIPV6 := "[::]:" + httpsPort
|
httpsPortIPV6 := "[::]:" + strconv.Itoa(httpsPort)
|
||||||
|
|
||||||
server.UpdateListen(httpsPort, website.DefaultServer, "ssl", "http2")
|
server.UpdateListen(strconv.Itoa(httpsPort), website.DefaultServer, "ssl", "http2")
|
||||||
if website.IPV6 {
|
if website.IPV6 {
|
||||||
server.UpdateListen(httpsPortIPV6, website.DefaultServer, "ssl", "http2")
|
server.UpdateListen(httpsPortIPV6, website.DefaultServer, "ssl", "http2")
|
||||||
}
|
}
|
||||||
@ -626,7 +630,7 @@ func applySSL(website model.Website, websiteSSL model.WebsiteSSL, req request.We
|
|||||||
if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := createPemFile(website, websiteSSL); err != nil {
|
if err := createPemFile(*website, websiteSSL); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
nginxParams := getNginxParamsFromStaticFile(dto.SSL, []dto.NginxParam{})
|
nginxParams := getNginxParamsFromStaticFile(dto.SSL, []dto.NginxParam{})
|
||||||
@ -651,7 +655,7 @@ func applySSL(website model.Website, websiteSSL model.WebsiteSSL, req request.We
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := updateNginxConfig(constant.NginxScopeServer, nginxParams, &website); err != nil {
|
if err := updateNginxConfig(constant.NginxScopeServer, nginxParams, website); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -297,7 +297,7 @@ var AddTask = &gormigrate.Migration{
|
|||||||
}
|
}
|
||||||
|
|
||||||
var UpdateWebsite = &gormigrate.Migration{
|
var UpdateWebsite = &gormigrate.Migration{
|
||||||
ID: "20240803-update-website",
|
ID: "20240807-update-website",
|
||||||
Migrate: func(tx *gorm.DB) error {
|
Migrate: func(tx *gorm.DB) error {
|
||||||
return tx.AutoMigrate(
|
return tx.AutoMigrate(
|
||||||
&model.Website{})
|
&model.Website{})
|
||||||
|
@ -288,6 +288,7 @@ export namespace Website {
|
|||||||
SSLProtocol: string[];
|
SSLProtocol: string[];
|
||||||
algorithm: string;
|
algorithm: string;
|
||||||
hsts: boolean;
|
hsts: boolean;
|
||||||
|
httpsPort: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CheckReq {
|
export interface CheckReq {
|
||||||
|
@ -13,10 +13,13 @@
|
|||||||
<el-switch v-model="form.enable" @change="changeEnable"></el-switch>
|
<el-switch v-model="form.enable" @change="changeEnable"></el-switch>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div v-if="form.enable">
|
<div v-if="form.enable">
|
||||||
|
<el-form-item :label="'HTTPS ' + $t('commons.table.port')" prop="httpsPort">
|
||||||
|
<el-input v-model.number="form.httpsPort" />
|
||||||
|
</el-form-item>
|
||||||
<el-text type="warning" class="!ml-2">{{ $t('website.ipWebsiteWarn') }}</el-text>
|
<el-text type="warning" class="!ml-2">{{ $t('website.ipWebsiteWarn') }}</el-text>
|
||||||
<el-divider content-position="left">{{ $t('website.SSLConfig') }}</el-divider>
|
<el-divider content-position="left">{{ $t('website.SSLConfig') }}</el-divider>
|
||||||
<el-form-item :label="$t('website.HTTPConfig')" prop="httpConfig">
|
<el-form-item :label="$t('website.HTTPConfig')" prop="httpConfig">
|
||||||
<el-select v-model="form.httpConfig" class="p-w-200">
|
<el-select v-model="form.httpConfig" class="p-w-400">
|
||||||
<el-option :label="$t('website.HTTPToHTTPS')" :value="'HTTPToHTTPS'"></el-option>
|
<el-option :label="$t('website.HTTPToHTTPS')" :value="'HTTPToHTTPS'"></el-option>
|
||||||
<el-option :label="$t('website.HTTPAlso')" :value="'HTTPAlso'"></el-option>
|
<el-option :label="$t('website.HTTPAlso')" :value="'HTTPAlso'"></el-option>
|
||||||
<el-option :label="$t('website.HTTPSOnly')" :value="'HTTPSOnly'"></el-option>
|
<el-option :label="$t('website.HTTPSOnly')" :value="'HTTPSOnly'"></el-option>
|
||||||
@ -101,7 +104,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-form-item :label="' '" v-if="websiteSSL && websiteSSL.id > 0">
|
<el-form-item :label="' '" v-if="websiteSSL && websiteSSL.id > 0">
|
||||||
<el-descriptions :column="6" border direction="vertical">
|
<el-descriptions :column="7" border direction="vertical">
|
||||||
<el-descriptions-item :label="$t('website.primaryDomain')">
|
<el-descriptions-item :label="$t('website.primaryDomain')">
|
||||||
{{ websiteSSL.primaryDomain }}
|
{{ websiteSSL.primaryDomain }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
@ -170,7 +173,7 @@ import { GetHTTPSConfig, ListSSL, SearchAcmeAccount, UpdateHTTPSConfig } from '@
|
|||||||
import { ElMessageBox, FormInstance } from 'element-plus';
|
import { ElMessageBox, FormInstance } from 'element-plus';
|
||||||
import { computed, onMounted, reactive, ref } from 'vue';
|
import { computed, onMounted, reactive, ref } from 'vue';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import { Rules } from '@/global/form-rules';
|
import { Rules, checkNumberRange } from '@/global/form-rules';
|
||||||
import { dateFormatSimple, getProvider, getAccountName } from '@/utils/util';
|
import { dateFormatSimple, getProvider, getAccountName } from '@/utils/util';
|
||||||
import { MsgSuccess } from '@/utils/message';
|
import { MsgSuccess } from '@/utils/message';
|
||||||
import FileList from '@/components/file-list/index.vue';
|
import FileList from '@/components/file-list/index.vue';
|
||||||
@ -201,6 +204,7 @@ const form = reactive({
|
|||||||
algorithm:
|
algorithm:
|
||||||
'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:!aNULL:!eNULL:!EXPORT:!DSS:!DES:!RC4:!3DES:!MD5:!PSK:!KRB5:!SRP:!CAMELLIA:!SEED',
|
'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:!aNULL:!eNULL:!EXPORT:!DSS:!DES:!RC4:!3DES:!MD5:!PSK:!KRB5:!SRP:!CAMELLIA:!SEED',
|
||||||
SSLProtocol: ['TLSv1.3', 'TLSv1.2', 'TLSv1.1', 'TLSv1'],
|
SSLProtocol: ['TLSv1.3', 'TLSv1.2', 'TLSv1.1', 'TLSv1'],
|
||||||
|
httpsPort: 443,
|
||||||
});
|
});
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const ssls = ref();
|
const ssls = ref();
|
||||||
@ -218,6 +222,7 @@ const rules = ref({
|
|||||||
SSLProtocol: [Rules.requiredSelect],
|
SSLProtocol: [Rules.requiredSelect],
|
||||||
algorithm: [Rules.requiredInput],
|
algorithm: [Rules.requiredInput],
|
||||||
acmeAccountID: [Rules.requiredInput],
|
acmeAccountID: [Rules.requiredInput],
|
||||||
|
httpsPort: [Rules.requiredInput, checkNumberRange(1, 65535)],
|
||||||
});
|
});
|
||||||
const resData = ref();
|
const resData = ref();
|
||||||
const sslReq = reactive({
|
const sslReq = reactive({
|
||||||
@ -278,23 +283,27 @@ const get = () => {
|
|||||||
GetHTTPSConfig(id.value).then((res) => {
|
GetHTTPSConfig(id.value).then((res) => {
|
||||||
if (res.data) {
|
if (res.data) {
|
||||||
form.type = 'existed';
|
form.type = 'existed';
|
||||||
resData.value = res.data;
|
const data = res.data;
|
||||||
form.enable = res.data.enable;
|
resData.value = data;
|
||||||
if (res.data.httpConfig != '') {
|
form.enable = data.enable;
|
||||||
form.httpConfig = res.data.httpConfig;
|
if (data.httpConfig != '') {
|
||||||
|
form.httpConfig = data.httpConfig;
|
||||||
}
|
}
|
||||||
if (res.data.SSLProtocol && res.data.SSLProtocol.length > 0) {
|
if (data.SSLProtocol && data.SSLProtocol.length > 0) {
|
||||||
form.SSLProtocol = res.data.SSLProtocol;
|
form.SSLProtocol = data.SSLProtocol;
|
||||||
}
|
}
|
||||||
if (res.data.algorithm != '') {
|
if (data.algorithm != '') {
|
||||||
form.algorithm = res.data.algorithm;
|
form.algorithm = data.algorithm;
|
||||||
}
|
}
|
||||||
if (res.data.SSL && res.data.SSL.id > 0) {
|
if (data.SSL && data.SSL.id > 0) {
|
||||||
form.websiteSSLId = res.data.SSL.id;
|
form.websiteSSLId = data.SSL.id;
|
||||||
websiteSSL.value = res.data.SSL;
|
websiteSSL.value = data.SSL;
|
||||||
form.acmeAccountID = res.data.SSL.acmeAccountId;
|
form.acmeAccountID = data.SSL.acmeAccountId;
|
||||||
|
}
|
||||||
|
form.hsts = data.hsts;
|
||||||
|
if (data.httpsPort > 0) {
|
||||||
|
form.httpsPort = data.httpsPort;
|
||||||
}
|
}
|
||||||
form.hsts = res.data.hsts;
|
|
||||||
}
|
}
|
||||||
listSSL();
|
listSSL();
|
||||||
listAcmeAccount();
|
listAcmeAccount();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user