心雨纷扬的博客

一个简单的博客

0%

更改wsl2的存储位置(以docker,Ubuntu为例)

docker

  1. 退出docker

  2. 查看docker挂载信息wsl --list -v

  3. 导出、注销、导入docker-data,其中需要建立对应文件夹wsl\docker-data,wsl\docker,wsl\docker-

    1
    2
    3
    wsl --export docker-desktop-data "E:\wsl\wsl-data\docker-desktop-data.tar"
    wsl --unregister docker-desktop-data
    wsl --import docker-desktop-data "E:\wsl\docker\data" "E:\wsl\wsl-data\docker-desktop-data.tar" --version 2
  4. 导出、注销、导入docker-desktop

    1
    2
    3
    4
    wsl --export docker-desktop "E:\wsl\wsl-data\docker-desktop.tar"
    wsl --unregister docker-desktop
    wsl --import docker-desktop "E:\wsl\docker\desktop" "E:\wsl\wsl-data\docker-desktop.tar" --version 2

ubunutu

新建wsl\ubuntu目录

1
2
3
4
5
6
wsl --shutdown
wsl --export Ubuntu "E:\wsl\wsl-data\ubuntu.tar"
wsl --unregister Ubuntu
wsl --import Ubuntu "E:\wsl\ubuntu" "E:\wsl\wsl-data\ubuntu.tar" --version 2
#切换默认用户,我安装的时候设置的默认用户名是don
ubuntu config --default-user don

Gitlab EE安装与破解

安装

设置卷的路径

在设置其他所有内容之前,配置指向配置、日志和数据文件所在的目录的新环境变量。确保目录存在并授予适当的权限。$GITLAB_HOME

linux用户设置为/srv/gitlab

1
export GITLAB_HOME=/srv/gitlab

macos,使用用户目录,设置为$HOME/gitlab

1
export GITLAB_HOME=$HOME/gitlab
主机路径 容器路径 用途
$GITLAB_HOME/data /var/opt/gitlab 应用数据存储.
$GITLAB_HOME/logs /var/log/gitlab 日志存储.
$GITLAB_HOME/config /etc/gitlab Gitlab配置文件存储

使用Docker 引擎安装GitLab

1
2
3
4
5
6
7
8
9
sudo docker run --detach \
--hostname source.52dzd.com \
--publish 443:443 --publish 80:80 --publish 22:22 \
--name gitlab \
--restart always \
--volume $GITLAB_HOME/config:/etc/gitlab:Z \
--volume $GITLAB_HOME/logs:/var/log/gitlab:Z \
--volume $GITLAB_HOME/data:/var/opt/gitlab:Z \
gitlab/gitlab-ee:latest

如果你使用的是 SELinux,请使用以下命令替换:

1
2
3
4
5
6
7
8
9
sudo docker run --detach \
--hostname source.52dzd.com \
--publish 443:443 --publish 80:80 --publish 22:22 \
--name gitlab \
--restart always \
--volume $GITLAB_HOME/config:/etc/gitlab:Z \
--volume $GITLAB_HOME/logs:/var/log/gitlab:Z \
--volume $GITLAB_HOME/data:/var/opt/gitlab:Z \
gitlab/gitlab-ee:latest

使用 sudo docker logs -f gitlab 来跟踪启动进程,这个过程需要较长时间.

访问对应域名:source.52dzd.com,使用root用户名登录,密码使用以下命令来查看

1
sudo docker exec -it gitlab grep 'Password:' /etc/gitlab/initial_root_password

密码文件会在24小时后自动删除,请注意修改或者保存初始密码

使用 Docker Compose安装GitLab

  • 安装 Docker Compose

  • 新建文件:docker-compose.yml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    web:
    image: 'gitlab/gitlab-ee:latest'
    restart: always
    hostname: 'source.52dzd.com'
    environment:
    GITLAB_OMNIBUS_CONFIG: |
    external_url 'https://source.52dzd.com'
    # 添加任何其它的gitlab.rb配置这里,每个配置单独一行
    ports:
    - '80:80'
    - '443:443'
    - '22:22'
    volumes:
    - '$GITLAB_HOME/config:/etc/gitlab'
    - '$GITLAB_HOME/logs:/var/log/gitlab'
    - '$GITLAB_HOME/data:/var/opt/gitlab'
  • 在新建文件docker-compose.yml的目录里执行

    1
    docker-compose up -d

破解

  • 进入docker容器
1
sudo docker exec -it gitlab /bin/bash
  • 创建文件 vi license.rb

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    require "openssl"
    require "gitlab/license"

    key_pair = OpenSSL::PKey::RSA.generate(2048)
    File.open("license_key", "w") { |f| f.write(key_pair.to_pem) }

    public_key = key_pair.public_key
    File.open("license_key.pub", "w") { |f| f.write(public_key.to_pem) }

    private_key = OpenSSL::PKey::RSA.new File.read("license_key")
    Gitlab::License.encryption_key = private_key

    license = Gitlab::License.new
    license.licensee = {
    "Name" => "none",
    "Company" => "none",
    "Email" => "example@test.com",
    }
    license.starts_at = Date.new(2020, 1, 1) # 开始时间
    license.expires_at = Date.new(2050, 1, 1) # 结束时间
    license.notify_admins_at = Date.new(2049, 12, 1)
    license.notify_users_at = Date.new(2049, 12, 1)
    license.block_changes_at = Date.new(2050, 1, 1)
    license.restrictions = {
    active_user_count: 10000,
    }

    puts "License:"
    puts license

    data = license.export
    puts "Exported license:"
    puts data
    File.open("GitLabBV.gitlab-license", "w") { |f| f.write(data) }

    public_key = OpenSSL::PKey::RSA.new File.read("license_key.pub")
    Gitlab::License.encryption_key = public_key

    data = File.read("GitLabBV.gitlab-license")
    $license = Gitlab::License.import(data)

    puts "Imported license:"
    puts $license

    unless $license
    raise "The license is invalid."
    end

    if $license.restricted?(:active_user_count)
    active_user_count = 10000
    if active_user_count > $license.restrictions[:active_user_count]
    raise "The active user count exceeds the allowed amount!"
    end
    end

    if $license.notify_admins?
    puts "The license is due to expire on #{$license.expires_at}."
    end

    if $license.notify_users?
    puts "The license is due to expire on #{$license.expires_at}."
    end

    module Gitlab
    class GitAccess
    def check(cmd, changes = nil)
    if $license.block_changes?
    return build_status_object(false, "License expired")
    end
    end
    end
    end

    puts "This instance of GitLab Enterprise Edition is licensed to:"
    $license.licensee.each do |key, value|
    puts "#{key}: #{value}"
    end

    if $license.expired?
    puts "The license expired on #{$license.expires_at}"
    elsif $license.will_expire?
    puts "The license will expire on #{$license.expires_at}"
    else
    puts "The license will never expire."
    end
  • 生成证书

    1
    ruby license.rb

    生成 GitLabBV.gitlab-license license_key license_key.pub 这三个文件。

  • 替换默认公钥

    1
    cp -f license_key.pub /opt/gitlab/embedded/service/gitlab-rails/.license_encryption_key.pub
  • 升级到ULTIMATE版本

    修改文件 /opt/gitlab/embedded/service/gitlab-rails/ee/app/models/license.rb

    替换对应restricted_attr(:plan).presence || STARTER_PLANrestricted_attr(:plan).presence || ULTIMATE_PLAN

    大约位于367行

    • 重新配置gitlab

      1
      2
      gitlab-ctl reconfigure
      gitlab-ctl restart
    • 导入许可证

      登录gitlab后台,管理中心->许可证 (/admin/license),导入 GitLabBV.gitlab-license
      可以选择cat GitLabBV.gitlab-license打印出文件内容后,把密钥复制后使用密钥文本,而不是上传文件

参考文档

许可证生成
Gitlab EE安装与破解

install sqlserver 2019 on ubuntu 20.04

Prerequisites

sudo apt update

sudo apt upgrade

sudo apt install software-properties-common

sudo apt update

data disk mount

1
2
3
4
5
apt autoremove
fdisk -l
# 执行命令后,如果不存在/dev/vdb,表示您的实例没有数据盘。确认数据盘是否已挂载。
$ sudo fdisk -u /dev/vdb
# 执行后输入n开始新分区,后续均可回车使用默认值,最后输入 w 保存

运行fdisk -lu /dev/vdb命令查看新分区。

如果出现/dev/vdb1的相关信息,表示新分区已创建完成。

1
2
3
4
5
6
sudo mkfs -t ext4 /dev/vdb1 #创建文件系统
sudo cp /etc/fstab /etc/fstab.bak #备份etc/fstab
#把分区写入启动/etc/fstab,启动开机自动挂载分区
sudo echo `blkid /dev/vdb1 | awk '{print $2}' | sed 's/\"//g'` /mnt ext4 defaults 0 0 >> /etc/fstab
sudo mount /dev/vdb1 /mnt #挂载文件系统。
#如果运行df -h命令后出现新建文件系统的信息,表示文件系统挂载成功。

Install

wget -qO- https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -

sudo add-apt-repository "$(wget -qO- https://packages.microsoft.com/config/ubuntu/20.04/mssql-server-2019.list)"

sudo apt-get update

sudo apt-get install -y mssql-server

sudo /opt/mssql/bin/mssql-conf setup

1
2
3
4
5
SQL Server 2019
Enterprise:HMWJ3-KY3J2-NMVD7-KG4JR-X2G8G
Enterprise Core:2C9JR-K3RNG-QD4M4-JQ2HR-8468J
Strandard:PMBDC-FXVM3-T777P-N4FY8-PKFF4
Web:33QQK-WWQNB-G6T46-C86YB-TX2PH

Change the default master database file directory location

1
2
3
4
5
6
7
8
9
10
11
12
13
cd /mnt
mkdir sqlserver
chown mssql sqlserver
chgrp mssql sqlserver
cd sqlserver
mkdir masterdatabasedir
chown mssql masterdatabasedir
chgrp mssql masterdatabasedir
/opt/mssql/bin/mssql-conf set filelocation.masterdatafile /mnt/sqlserver/masterdatabasedir/master.mdf
/opt/mssql/bin/mssql-conf set filelocation.masterlogfile /mnt/sqlserver/masterdatabasedir/mastlog.ldf
systemctl stop mssql-server #Stop the SQL Server service:
mv /var/opt/mssql/data/master.mdf /mnt/sqlserver/masterdatabasedir/master.mdf
mv /var/opt/mssql/data/mastlog.ldf /mnt/sqlserver/masterdatabasedir/mastlog.ldf

Config

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/opt/mssql/bin/mssql-conf set telemetry.customerfeedback false  #不参与用户反馈
/opt/mssql/bin/mssql-conf set memory.memorylimitmb 4096 #内存设置限制4g
cd /mnt/sqlserver
mkdir data
mkdir log
mkdir bak
mkdir dump
mkdir logs
chgrp mssql data
chgrp mssql log
chgrp mssql bak
chgrp mssql dump
chgrp mssql logs
chown mssql data
chown mssql log
chown mssql bak
chown mssql dump
chown mssql logs
/opt/mssql/bin/mssql-conf set filelocation.defaultdatadir /mnt/sqlserver/data
/opt/mssql/bin/mssql-conf set filelocation.defaultlogdir /mnt/sqlserver/log
/opt/mssql/bin/mssql-conf set filelocation.defaultbackupdir /mnt/sqlserver/bak
/opt/mssql/bin/mssql-conf set filelocation.defaultdumpdir /mnt/sqlserver/dump
/opt/mssql/bin/mssql-conf set filelocation.errorlogfile /mnt/sqlserver/logs/errorlog
systemctl restart mssql-server

Deploy in Ubuntu –dev

System Init

阿里云上的ECS

数据盘挂载【按需操作】

1
2
3
4
5
6
7
$ sudo apt update
$ sudo apt upgrade -y
$ sudo apt autoremove
$ sudo fdisk -l
# 执行命令后,如果不存在/dev/vdb,表示您的实例没有数据盘。确认数据盘是否已挂载。
$ sudo fdisk -u /dev/vdb # 执行后输入n开始新分区,后续均可回车使用默认值,最后输入 w 保存

运行fdisk -lu /dev/vdb命令查看新分区。
如果出现/dev/vdb1的相关信息,表示新分区已创建完成。
sudo mkfs -t ext4 /dev/vdb1 创建文件系统
sudo cp /etc/fstab /etc/fstab.bak 备份etc/fstab
把分区写入启动/etc/fstab,启动开机自动挂载分区

1
2
3

sudo echo `blkid /dev/vdb1 | awk '{print $2}' | sed 's/\"//g'` /mnt ext4 defaults 0 0 >> /etc/fstab

运行sudo mount /dev/vdb1 /mnt命令挂载文件系统。
如果运行df -h命令后出现新建文件系统的信息,表示文件系统挂载成功。

Install docker & Config

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

#Install
$ sudo apt-get update

$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

$ sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"

$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io

#安装docker-compose
#请前往 https://github.com/docker/compose/releases 寻找最新版本的版本号进行替换,底下版本号为:1.27.2]
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.27.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
$ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
$ docker-compose --version

#修改存储路径
$ sudo service docker stop
$ sudo mv /var/lib/docker /mnt/docker
$ sudo ln -s /mnt/docker /var/lib/
$ sudo service docker start

#阿里云镜像地址登录阿里云后从https://cr.console.aliyun.com/cn-shenzhen/instances/mirrors获取
$ sudo mkdir -p /etc/docker
$ sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://u9bgtozi.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

安装nginx以及配置

nginx安装

sudo apt install nginx

证书申请以及安装

1
2
3
4
5
sudo add-apt-repository universe  
sudo apt-get update
sudo apt-get install certbot python3-certbot-nginx
#开始申请证书
certbot --nginx --domains sudomain.***.com

更新nginx配置

覆盖上传nginx文件夹的文件到/etc/nginx

1
2
3
4
5
sudo rm /etc/nginx/sites-available/default
sudo rm /etc/nginx/sites-enabled/default
#域名
sudo ln -s /etc/nginx/sites-available/sudomain.***.com.conf /etc/nginx/sites-enabled/sudomain.***.com.conf
sudo service nginx restart

【可选操作】加密网站访问,使用用户名密码

1
2
sudo apt-get install apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd Javen

修改对应server的配置节

1
2
3
4
5
6
location / {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
vhost_traffic_status_display;
vhost_traffic_status_display_format html;
}

增强安全配置【仅在未使用certbot时使用】

生成 dhparam.pem 文件, 在命令行执行任一方法:

方法1: 很慢

openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048

方法2: 较快

与方法1无明显区别. 2048位也足够用, 4096更强

openssl dhparam -dsaparam -out /etc/nginx/ssl/dhparam.pem 4096

更新说明

2021-10-16日更新,
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.27.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
自从v2.0,版本号前面需要加v,如https://github.com/docker/compose/releases/download/v2.0.1/docker-compose-$(uname -s)-$(uname -m)

abp vnext 学习第一弹

dotnet tool install -g Volo.Abp.Cli

abpcli

创建没有手机端的项目

abp new Acme.BookStore -t app -d ef -u mvc -m none

等同命令

abp new Acme.BookStore -template app --database-provider ef --ui mvc --mobile none

修改对应项目连接字符串

修改Acme.BookStore.DbMigrator和Web项目的appsetting的连接字符串

数据迁移

执行Acme.BookStore.DbMigrator项目

或者,您可以在Visual Studio的程序包管理器控制台中运行Update-Database命令以应用迁移。

执行web项目

通用枚举遍历

如果你确认你的枚举类型是 int32,可以使用以下方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

/// <summary>
/// 将一个指定的枚举定义(Int)转换成集合对象.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static void ToList<T>() where T:Enum
{
Array datas = Enum.GetValues(typeof(T));

for (var i = 0; i < datas.Length; i++)
{
object value = datas.GetValue(i);
Console.WriteLine("{0,-9} {1}", value + ":",
(int)value);
//需要注意的是这里的强转(int)value ,所以这里需要你事先确认枚举基础类型,如果是byte,此处会抛出异常
}
}

有些时候你不能确认枚举的类型是int还是byte

demo示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

enum BEnum : byte
{
A ,
B ,
C
}

var type = typeof(BEnum);
FieldInfo[] fields = type.GetFields();
foreach (var field in fields)
{
if (field.FieldType!= type)
{
continue;
}
Console.WriteLine("{0,-9} {1}", field.Name + ":",
field.GetRawConstantValue());
//field.GetRawConstantValue() 获取数值
//field.Name 获取枚举值名称

}

输出结果

1
2
3
4
5

A: 0
B: 1
C: 2

C#控制台启动程序或者执行命令

C#启动程序

调用示例

1
StartAConsoleProcess(ygcApiExePath);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
private static void StartAConsoleProcess(string exePath, params string[] cmdText)
{
Process p = new Process();
p.StartInfo = new ProcessStartInfo(exePath);
p.StartInfo.UseShellExecute = false; //是否使用操作系统shell启动

if (exePath.Contains(Path.DirectorySeparatorChar))
{
var file = new FileInfo(exePath);
p.StartInfo.WorkingDirectory = file.Directory.FullName;
}

p.StartInfo.RedirectStandardInput = true;//接受来自调用程序的输入信息
p.StartInfo.RedirectStandardOutput = true;//由调用程序获取输出信息
p.StartInfo.RedirectStandardError = true;//重定向标准错误输出
p.StartInfo.CreateNoWindow = true;//不显示程序窗口
p.OutputDataReceived += YgcApi_OutputDataReceived;
p.ErrorDataReceived += YgcApi_ErrorDataReceived;
p.Start();
p.BeginOutputReadLine();
p.BeginErrorReadLine();
if (cmdText.Length > 0)
{
foreach (var item in cmdText)
{
p.StandardInput.WriteLine(item);
//向cmd窗口发送输入信息
p.StandardInput.AutoFlush = true;
}
}
}

调用cmd执行命令

调用示例:

1
RunCommand("cd D:\\viewerSevice", "d:", "dotnet Ygc.Service.3DViewerService.dll");
1
2
3
4
private static void RunCommand(params string[] cmdText)
{
StartAConsoleProcess(exePath: "cmd.exe", cmdText);
}

windows删除无法访问的文件

现象

通过文件/文件夹的属性的安全选项卡,无法修改所有者和权限

界面上提示:win10 你没有权限查看或编辑这个对象

解决办法

按下 (Windows 徽标键 +X键),点击“命令提示符(管理员)”,复制以下命令并在命令提示符中点击鼠标右键,点击“粘贴”,随后按回车键(Enter)执行:

del /Q '待删除文件路径'

命令完成后重新启动计算机,查看截图3.png是否依然存在,如果存在,再次打开命令提示符(管理员)复制以下命令并粘贴执行:

1
ATTRIB 待删除文件路径>%temp%\pngA.txt & FSUTIL usn readdata 待删除文件路径>>%temp%\pngA.txt & icacls 待删除文件路径>>%temp%\pngA.txt & %temp%\pngA.txt

我试过执行完第一个命令,然后重启电脑就正常了。

参考文档

当前环境

  1. Net Core 2.2+ //建议使用Net Core 3.0

  2. Asp.Net Framework 4.6.2+

  3. Visual Studio 2019//如果使用Net Core 3.0,你可能需要预览版

新增空的解决方案

  1. 打开命令行。执行dotnet new sln -n SsoTest 建立空白解决方案。

新增Identity Server4 服务端【本文不讨论服务端配置问题】

新增项目并添加到解决方案里

  1. 打开命令行或者powershell

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # 新增IdentityServer4模板
    dotnet new -i IdentityServer4.Templates
    # 新建项目
    dotnet new is4empty -n IdentityServer
    # 添加到解决方案
    dotnet sln add .\IdentityServer\IdentityServer.csproj
    # 进入项目目录
    cd IdentityServer
    # 添加UI
    dotnet new is4ui
  2. 修改Config.cs文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    using IdentityServer4;
    using IdentityServer4.Models;
    using IdentityServer4.Test;
    using System.Collections.Generic;
    using System.Security.Claims;

    namespace IdentityServer
    {
    public static class Config
    {
    public static IEnumerable<IdentityResource> GetIdentityResources()
    {
    return new IdentityResource[]
    {
    new IdentityResources.OpenId(),
    new IdentityResources.Profile(),
    new IdentityResources.Email(),
    new IdentityResources.Phone(),
    };
    }
    public static List<TestUser> GetUsers()
    {
    return new List<TestUser> {
    new TestUser {
    SubjectId = "1",
    Username = "alice",
    Password = "password",
    Claims = new []
    {
    new Claim("name", "Alice"),
    new Claim("website", "https://alice.com")
    }
    },
    new TestUser {
    SubjectId = "2",
    Username = "bob",
    Password = "password",
    Claims = new []
    {
    new Claim("name", "Bob"),
    new Claim("website", "https://bob.com")
    }
    }
    };
    }
    public static IEnumerable<ApiResource> GetApis()
    {
    return new ApiResource[] {
    new ApiResource ("api1", "My API")
    };
    }

    public static IEnumerable<Client> GetClients()
    {
    var secret = "49C1A7E1-0C79-4A89-A3D6-A37998FB86B0".Sha256();
    return new Client[] {
    new Client {
    ClientId = "mvc",
    ClientName = "MVC Client",
    ClientSecrets = {
    new Secret (secret)
    },
    AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
    // where to redirect to after login
    RedirectUris = { "http://localhost:5001/signin-oidc" },
    // where to redirect to after logout
    PostLogoutRedirectUris = { "http://localhost:5001/signout-callback-oidc" },
    AllowedScopes = new List<string> {
    IdentityServerConstants.StandardScopes.OpenId,
    IdentityServerConstants.StandardScopes.Email,
    IdentityServerConstants.StandardScopes.Phone,
    IdentityServerConstants.StandardScopes.Profile,
    "api1"
    }
    },,
    new Client
    {
    ClientName = "vuejs",
    ClientId = "vuejsclient",
    AllowedGrantTypes=GrantTypes.Implicit,
    AllowAccessTokensViaBrowser=true,
    AccessTokenType = AccessTokenType.Reference,
    UpdateAccessTokenClaimsOnRefresh = true,
    AllowOfflineAccess = true,
    RequireConsent = false,
    //AccessTokenLifetime = 50,
    RedirectUris = new List<string>()
    {
    "http://localhost:5002/static/callback.html",
    "http://localhost:5002/static/silent-renew.html"
    },
    PostLogoutRedirectUris = {
    "http://localhost:5002/index.html"
    },
    AllowedCorsOrigins = {
    "http://localhost:5002"
    },
    AllowedScopes =
    {
    IdentityServerConstants.StandardScopes.OpenId,
    IdentityServerConstants.StandardScopes.Profile,
    IdentityServerConstants.StandardScopes.Address,
    "roles",
    "identityserver4api",
    "country",
    "subscriptionlevel"
    },
    ClientSecrets =
    {
    new Secret("secret".Sha256())
    }
    }
    };
    }
    }
    }
  3. 修改Startup.cs,取消注释

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    public IHostingEnvironment Environment { get; }

    public Startup(IHostingEnvironment environment)
    {
    Environment = environment;
    }

    public void ConfigureServices(IServiceCollection services)
    {
    // uncomment, if you want to add an MVC-based UI
    services.AddMvc().SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_2_1);

    var builder = services.AddIdentityServer()
    .AddInMemoryIdentityResources(Config.GetIdentityResources())
    .AddInMemoryApiResources(Config.GetApis())
    .AddInMemoryClients(Config.GetClients())
    .AddTestUsers(Config.GetUsers());

    if (Environment.IsDevelopment())
    {
    builder.AddDeveloperSigningCredential();
    }
    else
    {
    throw new Exception("need to configure key material");
    }
    }

    public void Configure(IApplicationBuilder app)
    {
    if (Environment.IsDevelopment())
    {
    app.UseDeveloperExceptionPage();
    }

    // uncomment if you want to support static files
    app.UseStaticFiles();

    app.UseIdentityServer();
    // uncomment, if you want to add an MVC-based UI
    app.UseMvcWithDefaultRoute();
    }
  4. 新开一个命令行或者powershell窗口,运行服务端

    1
    2
    3
    4
    5
    6

    # 还原nuget,编译
    dotnet restore
    dotnet build
    # 运行
    dotnet run

新增一个空的WebApi项目

  1. 打开解决方案SsoTest.sln
  2. 在解决方案上右键->添加->新建项目,创建WebApi项目,名为SSOTest.WebApi



配置WebApi接入Identity Server

  1. 修改项目属性,指定web端口为5002

  2. 打开包控制台,安装nuget包

    1
    2
    3
    Install-Package IdentityModel -Version 3.10.10
    Install-Package IdentityServer3.Contrib.AccessTokenValidation
    Install-Package Microsoft.Owin.Host.SystemWeb
  3. 新增OWIN的Startup.cs文件

  4. 修改为Startup.cs文件.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    using System;
    using System.Net.Http;
    using System.Security.Claims;
    using System.Web.Helpers;
    using IdentityModel;
    using IdentityModel.Client;
    using Microsoft.Owin;
    using Microsoft.Owin.Security;
    using Microsoft.Owin.Security.Cookies;
    using Microsoft.Owin.Security.OpenIdConnect;
    using Owin;

    [assembly: OwinStartup(typeof(SSOTest.Client.Startup))]

    namespace SSOTest.Client
    {
    public partial class Startup
    {
    public void Configuration(IAppBuilder app)
    {
    // 有关如何配置应用程序的详细信息,请访问 https://go.microsoft.com/fwlink/?LinkID=316888
    ConfigureAuth(app);
    }

    private void ConfigureAuth(IAppBuilder app)
    {
    var secret = "49C1A7E1-0C79-4A89-A3D6-A37998FB86B0".ToSha256();
    AntiForgeryConfig.UniqueClaimTypeIdentifier = "sub";
    app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
    {
    Authority = "http://localhost:5000",
    RequiredScopes = new string[] { "webapi" },
    ClientId = "Test",
    ClientSecret = secret,
    DelayLoadMetadata = true
    });
    }
    }
    }
  5. 打开Controllers/ValuesController.cs
    Get这个Action上加特性[Authorize]

  6. 运行Client项目,访问 http://localhost:5002/Api/Values

源码下载

on the github