分类 Abp 下的文章

步骤

引入Volo.Abp.Emailing 包

并在模块中添加对应的依赖。

    [DependsOn(
        typeof(AbpEmailingModule)
   )]
    public class XXXXModule : AbpModule
    {

添加配置

在appsettings.json中添加如下代码:

"Settings": {
  "Abp.Mailing.Smtp.Host": "127.0.0.1",
  "Abp.Mailing.Smtp.Port": "25",
  "Abp.Mailing.Smtp.UserName": "",
  "Abp.Mailing.Smtp.Password": "",
  "Abp.Mailing.Smtp.Domain": "",
  "Abp.Mailing.Smtp.EnableSsl": "false",
  "Abp.Mailing.Smtp.UseDefaultCredentials": "true",
  "Abp.Mailing.DefaultFromAddress": "noreply@abp.io",
  "Abp.Mailing.DefaultFromDisplayName": "ABP application"
}

这里需要特别注意一下,其中的password项目,不可直接填写,abp要求必须对密码进行加密处理,如果你直接填写密码。在发送邮件时会抛出如下异常:

 The input data is not a complete block.
System.Security.Cryptography.CryptographicException: The input data is not a complete block.
   at Internal.Cryptography.UniversalCryptoDecryptor.UncheckedTransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
   at Internal.Cryptography.UniversalCryptoTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
   at System.Security.Cryptography.CryptoStream.ReadAsyncCore(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken, Boolean useAsync)

参考官方文档,要么,使用ISettingManager 进行配置。如果使用appsettings.json进行配置,就需要自行加密后,填写密文。

这里说下第二种,如何进行加密呢?我们可自己下一段端代码,对密码进行加密,调试方式获取加密字符串后,再把这段代码删除即可。
代码如下_settingDefinitionManager和_settingEncryptionService注入即可,用完再删除就行。

private readonly ISettingEncryptionService _settingEncryptionService;
private readonly ISettingDefinitionManager _settingDefinitionManager;
public TestAppService(
    ISettingEncryptionService settingEncryptionService,
    ISettingDefinitionManager settingDefinitionManager)
{

    _settingEncryptionService = settingEncryptionService;
    _settingDefinitionManager = settingDefinitionManager;
}

public async Task EncryptPwd()
{

    var setting = _settingDefinitionManager.Get(EmailSettingNames.Smtp.Password);
    var psd = _settingEncryptionService.Encrypt(setting,"密码");
}

这样,得到了加密后的密码,配置上就可了。

使用

使用的时候,也是非常简单,直接依赖注入方式注入IEmailSender,然后执行SendAsync接口。

private readonly IEmailSender _emailSender;
public TestAppService(
    IEmailSender emailSender)
{
    _emailSender= emailSender;
}

public async Task SendTest()
{
    await _emailSender.SendAsync("123456789@qq.com",
        "测试",
        "正文内容.....");
}

当然,实际使用中,可能还会用到模板等内容,这里不再赘述,参考官方文档吧。

背景

在使用abp vNext开发过程中,因项目使用的是ef core作为ORM工具,而Ef的批量操作性能并不能让人满意。于是便有了使用原生sql操作数据库的需求。

使用

既然说到使用了abp vNext,那肯定利用abp的功能实现更为方便。代码如下:

方式一

第一种情况,可以获取到仓储对象,Repository。无需在意哪个实体的仓储,任意实体仓储

private async Task ExecuteSql(string sql)
{
    using (var dbContext = _coursewareRepository.GetDbContext())
    {
        var aa =await dbContext.Database.ExecuteSqlRawAsync(sql);
    }
}

方式二

正常情况下,上述方式可以满足正常使用了,但是如果使用了后台任务,在后台任务中使用sql,该方式会报cannot access a disposed object的错误,提示dbContext已被释放。可通过以下方式进行使用。

private async Task ExecuteSql(string sql)
{
    using (var scope = ServiceScopeFactory.CreateScope())
    {
        var db = scope.ServiceProvider.GetService<IdeologyFrontDbContext>();
        var a = await db.Database.ExecuteSqlRawAsync(sql);
    }
}

背景

项目开发采用的是vue+abp WebApi方式,开发过程中发现有跨域问题。

解决方案

XXXHostModule类中ConfigureServices方法下添加如下代码:

var configuration = context.Services.GetConfiguration();
var hostingEnvironment = context.Services.GetHostingEnvironment();

ConfigureCors(context, configuration);

ConfigureCors方法如下:


private const string DefaultCorsPolicyName = "Default";
private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration)
{
    context.Services.AddCors(options =>
    {
        options.AddPolicy(DefaultCorsPolicyName, builder =>
        {
            builder
                //.AllowAnyOrigin()
                .WithOrigins(
                    configuration["App:CorsOrigins"]
                        .Split(",", StringSplitOptions.RemoveEmptyEntries)
                        .Select(o => o.RemovePostFix("/"))
                        .ToArray()
                )
                .WithAbpExposedHeaders()
                .SetIsOriginAllowedToAllowWildcardSubdomains()
                .AllowAnyHeader()
                .AllowAnyMethod()
                .AllowCredentials();
        });
    });
}

XXXHostModule类中OnApplicationInitialization方法下添加如下代码:

var app = context.GetApplicationBuilder();

app.UseCors(DefaultCorsPolicyName);

appsettings.json中添加如下配置,根据需求进行添加,本示例为开发环境配置,所以加入了localhost:8080

  "App": {
    "CorsOrigins": "http://localhost:8080,http://10.10.10.144:8080,*"
  }

完成,这样就可以进行跨域访问了

背景

项目开发过程中,需要在Application层使用当前用户的Username和Name,然而查看CurrentUser发现,Name属性竟然为null,而UserName正常显示。

处理

查看了AuthServer的数据初始化代码,也没发现什么问题,

QQ截图20201126133430.jpg

明明已经添加了name的Claim,但是却无法显示,而Email则正常显示。于是猜测可能是这里的名为name的Claim并非CurrentUser中的Name属性。为了验证,我查看了abp vNext的源码,找到了AbpUserClaimsPrincipalFactory 类,代码如下:

 public class AbpUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<IdentityUser, IdentityRole>, ITransientDependency
    {
        public AbpUserClaimsPrincipalFactory(
            UserManager<IdentityUser> userManager,
            RoleManager<IdentityRole> roleManager,
            IOptions<IdentityOptions> options)
            : base(
                  userManager,
                  roleManager,
                  options)
        {
        }

        [UnitOfWork]
        public async override Task<ClaimsPrincipal> CreateAsync(IdentityUser user)
        {
            var principal = await base.CreateAsync(user);
            var identity = principal.Identities.First();

            if (user.TenantId.HasValue)
            {
                identity.AddIfNotContains(new Claim(AbpClaimTypes.TenantId, user.TenantId.ToString()));
            }

            if (!user.Name.IsNullOrWhiteSpace())
            {
                identity.AddIfNotContains(new Claim(AbpClaimTypes.Name, user.Name));
            }

            if (!user.Surname.IsNullOrWhiteSpace())
            {
                identity.AddIfNotContains(new Claim(AbpClaimTypes.SurName, user.Surname));
            }

            if (!user.PhoneNumber.IsNullOrWhiteSpace())
            {
                identity.AddIfNotContains(new Claim(AbpClaimTypes.PhoneNumber, user.PhoneNumber));
            }

            identity.AddIfNotContains(new Claim(AbpClaimTypes.PhoneNumberVerified, user.PhoneNumberConfirmed.ToString()));

            if (!user.Email.IsNullOrWhiteSpace())
            {
                identity.AddIfNotContains(new Claim(AbpClaimTypes.Email, user.Email));
            }

            identity.AddIfNotContains(new Claim(AbpClaimTypes.EmailVerified, user.EmailConfirmed.ToString()));

            return principal;
        }
    }
}

## 解决方案

这里,我们看到了 AbpClaimTypes.Name 的名称,此名称应该为Name的Claim名称,我直接将其添加到了commonApiUserClaims列表中,发现命名空间下没有该属性,当时Apb版本为3.0.5,升级至3.2.1后,已经可以使用,o(╯□╰)o。之后再次调试,发现已经可以获得Name属性了。

 private async Task CreateApiResourcesAsync()
        {
            var commonApiUserClaims = new[]
            {
                //"email",
                //"email_verified",
                "name",
                //"phone_number",
                //"phone_number_verified",
                //"role",
                AbpClaimTypes.Name
            };

            await CreateApiResourceAsync("IdentityService", commonApiUserClaims);
            await CreateApiResourceAsync("InternalGateway", commonApiUserClaims);
            await CreateApiResourceAsync("WebAppGateway", commonApiUserClaims);
            //await CreateApiResourceAsync("TenantService", commonApiUserClaims);
            await CreateApiResourceAsync("IdeologyFrontService", commonApiUserClaims);
        }

1、准备工作

升级系统

$ sudo yum clean all
$ sudo yum update

查看系统版本
$ cat /etc/redhat-release

检查是否安装wget命令,后面会用到

如未安装,使用以下命令进行安装
yum install -y wget

切换yum源,不然可能会太慢

备份源文件
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
下载新的源,以下两个任选一个即可
阿里的:wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
网易的:wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo
清除系统yum缓存,并且将服务器上的软件包信息重新生成缓存到本地
yum clean all
yum makecache
更新yum
yum update -y

2、安装docker

安装所需的包 yum-utils
yum install -y yum-utils device-mapper-persistent-data lvm2

设置阿里云稳定版本的docker的源
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

centos8默认使用podman代替docker,所以需要containerd.io
yum install https://download.docker.com/linux/fedora/30/x86_64/stable/Packages/containerd.io-1.2.6-3.3.fc30.x86_64.rpm

安装最新稳定版的docker-ce
yum install docker-ce docker-ce-cli containerd.io

启动并加入开机启动
$ sudo systemctl start docker
$ sudo systemctl enable docker

验证安装是否成功(有client和service两部分表示docker安装启动都成功了)
$ docker version

docker-compose版本选择

curl -L https://github.com/docker/compose/releases/download/1.26.2/docker-compose-uname -s-uname -m -o /usr/local/bin/docker-compose

chmod +x /usr/local/bin/docker-compose

查看docker-compose版本
docker-compose version

3、安装Jenkins

安装JDK

yum install -y java

安装git

因我们需要在jenkins中配置git,所以需要安装,如不需,可不安装
yum install git
查看版本
git --version

添加Jenkins库到yum库

Jenkins将从这里下载安装
wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key

安装jenkins

yum install -y jenkins
安装过程完成后,启动Jenkins服务并启用它以在系统引导时启动

sudo systemctl start jenkins

sudo systemctl enable jenkins

端口默认8080,如需修改端口号:
配置jenkis的端口
vi /etc/sysconfig/jenkins
找到修改端口号:
JENKINS_PORT="8080"

4.配置Jenkins

gitlab创建账号,用于jenkins使用

根据你再jenkins中配置的令牌方式不同,需要在gitlab中生成访问令牌。我自己试了几次,都有问题,干脆直接在jenkins中配置了gitlab的用户名和密码,所以这里只创建了账号,配置下项目的角色权限就OK了,没有其他操作了

安装插件

  • Git Parameter ( 用于参数化构建中动态获取项目分支 )
  • Generic Webhook Trigger ( 用于解析 Webhook 传过来的参数 )
  • GitLab ( 用于推送构建结果给 GitLab )
    安装插件的方法,如下图:

找到插件管理界面
QQ截图20201120111229.png

如图所示进行搜索安装
QQ截图20201120111314.png

5、添加项目部署

新建项目

选择FreeStyle project 类型

填写源码管理

如图所示,因为我们尚未配置和选择Credentials,所以会如出现下面红色的错误,选择添加-Jenkins,进行配置凭证,

QQ截图20201120111949.png

添加过程如下,我直接使用了账号密码方式,所以设置如下,如果你需要使用 gitlab pai token 方式,还需要到gitlab进行配置,具体自行google。

QQ截图20201120112227.png

保存后,返回选择我们刚创建的credentials即可。
这里需要注意一点,如果你的gitlab地址是https协议的,配置完成后提示git server certificate verification failed,CAfile: none CRLfile: none错误,那么需要在配置关闭git的全局ssl验证。在Jenkins所在服务器执行如下命令

git config --global http.sslVerify false

因我的Jenkins采用docker部署,所需要先进入docker容器在执行:

[root@localhost ~]# docker exec -it jenkins /bin/bash
jenkins@b48982ee1421:/$ git config --global http.sslVerify false

QQ截图20201120112419.png

编写Shell脚本

构建项目中,我们选择执行shell脚本,

因我不想在服务器上编译程序,所以我选择了在本地编译发布后,将发布文件夹也上传到gitlab中,虽然这样不是很好,但首先提高了Jenkins部署效率,而且省去了好多的gitlab配置。

脚本如下:

#!/bin/sh
cd /var/lib/jenkins/workspace/test-auth/testAuthServer.Host
docker container prune << EOF
y
EOF
docker container ls -a | grep "test-auth"
if [ $? -eq 0 ];then
    docker container stop test-auth
    docker container rm test-auth
fi
docker image prune << EOF
y
EOF

docker build -t test-auth .
docker run -d -p 5001:80 --name=test-auth test-auth

DockerFile文件如下:

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80

COPY /bin/Release/netcoreapp3.1/publish .
ENTRYPOINT ["dotnet", "testAuthServer.Host.dll"]

然后再修改其他项目配置文件,并部署其他项目。

6、其他

docker安装redis

docker pull redis:latest
docker run -itd -d --name redis-test -p 6379:6379 redis

防火墙开放端口

查看当前已经开放的端口:

firewall-cmd --list-ports
开启端口,以8888为例:

firewall-cmd --zone=public --add-port=8888/tcp --permanent
重启防火墙:

firewall-cmd --reload

Nginx安装

https://www.cnblogs.com/zhizihuakai/p/12055618.html

sudo /usr/local/nginx/nginx         # 启动
/usr/local/nginx/nginx -s reload    # 重新载入配置文件
/usr/local/nginx/nginx -s reopen    # 重启 Nginx
/usr/local/nginx/nginx -s stop      # 停止 Nginx