首页
归档
友链
关于
Search
1
网易云音乐黑胶会员月月免费赠送
4,211 阅读
2
十年之约RSS聚合订阅服务上线
3,958 阅读
3
工资发放日的区别
2,896 阅读
4
rsyslogd内存占用过高解决方案
2,632 阅读
5
Nginx反代MinIO后,上传文件签名异常
2,468 阅读
零碎
标本
码海
工具
其他
登录
Search
标签搜索
北京
摄影
生活
Java
旅行
学习笔记
教程
服务器
Linux
日记
软件
SpringBoot
服务
Windows
数据库
福利
Spring
系统
SQL
php
萧瑟
累计撰写
209
篇文章
累计收到
1,522
条评论
首页
栏目
零碎
标本
码海
工具
其他
页面
归档
友链
关于
搜索到
47
篇与
码海
的结果
2025-08-25
OpenID Connect(OIDC) WordPress v1.0.0插件
Typecho的OIDC插件更新完了,咱们来说说WordPress插件。插件特点支持 PHP 7.0+ 、WordPress 5.8+、基于邮箱进行自动绑定、支持新建用户。安装方法1:手动安装下载插件文件将插件文件夹上传到 /wp-content/plugins/ 目录在WordPress管理后台激活插件进入"设置" > "OIDC设置"进行配置2:通过WordPress上传在WordPress管理后台进入"插件" > "安装插件"点击"上传插件"选择插件ZIP文件并上传激活插件并进行配置基本配置客户端ID: 从OIDC提供商获取的客户端标识符客户端密钥: 从OIDC提供商获取的客户端密钥发现URL: OIDC提供商的发现文档URL重定向URI: OIDC提供商回调的URI地址作用域: 请求的OIDC作用域(默认:openid profile email)高级配置启用OIDC登录: 在登录页面显示OIDC登录按钮自动创建用户: 如果用户不存在,自动创建WordPress用户账户自动链接用户: 自动链接OIDC用户与现有WordPress用户(基于邮箱)支持的OIDC提供商Google OAuth 2.0Microsoft Azure ADAuth0Keycloak其他符合OIDC标准的提供商使用说明可详细参考插件内的README.md下载地址下载地址
2025年08月25日
26 阅读
2 评论
2025-08-25
OpenID Connect(OIDC) Typecho v1.2.0插件
最近一直在研究“统一认证”,了解到了OIDC ,即OpenID Connect。OpenID Connect 是基于OAuth 2.0的身份认证协议,增加了Id Token。OIDC是OAuth2.0的超集,可以理解为OIDC=身份认证+OAuth2.0. OAuth2.0主要定义了资源的授权,而OIDC主要关注的是身份的认证。(身份信息也属于资源,但是OAuth2.0中没有对身份信息包含哪些内容以及认证过程做完整定义)刚好我自己搭建了一套TOPIAM认证平台,顺手把之前写的OAuth2登录认证插件做个升级,还写了一个WordPress的OIDC插件,有需的朋友可以下载使用。插件效果插件使用下载地址选择Typecho插件的zip包,解压后将插件上传/usr/plugins这个目录下,然后登陆后台,在“控制台”下拉菜单中进入“插件管理”,激活OidcTypecho插件。激活后,需要配置 OIDC发现文档URL、OIDC系统名称、Client ID、Client Secret、用户名映射规则因为我这个系统只有单用户,所以做了一个用户名映射规则,具体可以看插件设置中的说明。OIDC系统回调地址为:https://your-site/oidc/callback下载地址下载地址
2025年08月25日
30 阅读
1 评论
2025-08-06
TOPIAM v1.1.0 源码启动及异常处理
TOPIAM源码启动教程及前端运行过程中的异常问题处理方案。 开源不易,请尊重开源的知识成果;码字不易,搬运请注明出处。
2025年08月06日
87 阅读
1 评论
2025-05-11
Typecho(1.2.1)免密登录研究笔记
最近在研究 Spring Cloud 微服务 框架,便研究了一下它的OAuth2认证模式,想着在Typecho中也对接下,后面就不用再次输入账号密码了,很是方便。其中技术难点,是 Typecho 的免密登录方式,看到官方文档说的是封装在了Widget_User组件中,开发人员可调用此组件免密登录。但是验证了好久,都无法登录成功,又研究了聚合登录的插件中的免密登录(见下方)方法,也不是很好使。//使用用户uid登录 private function useUidLogin($uid, $expire = 0) { $authCode = function_exists('openssl_random_pseudo_bytes') ? bin2hex(openssl_random_pseudo_bytes(16)) : sha1(Typecho_Common::randString(20)); $user = array('uid'=>$uid,'authCode'=>$authCode); Typecho_Cookie::set('__typecho_uid', $uid, $expire); Typecho_Cookie::set('__typecho_authCode', Typecho_Common::hash($authCode), $expire); //更新最后登录时间以及验证码 $this->db->query($this->db ->update('table.users') ->expression('logged', 'activated') ->rows(array('authCode' => $authCode)) ->where('uid = ?', $uid)); }这个是根据用户的 uid 进行免密登录,但是调用 $this->user->hasLogin() 来判断用户是否登录,一直是 false;查了查资料,看到了一篇《Typecho不改核心代码实现自定义登录、注册功能》文档,然后给了一个思路,研究一下1.2.1版本用户那块的代码;在/var/Widget/User.php中,用户登录跟聚合登录的方式一样,但是就是不好使,再向下有一个方法,叫 simpleLogin; 注解也写的很好“只需要提供uid或者完整user数组即可登录的方法, 多用于插件等特殊场合”,直接调用 $this->user->simpleLogin($uid),即可登录成功。只要思想不滑坡,方法总比困难多。
2025年05月11日
213 阅读
9 评论
2024-08-24
PostgreSQL:Unsupported binary encoding of timestamp.
报错信息服务启动后的前几次查询没有问题,多次查询后报这个错。org.postgresql.util.PSQLException:Unsupported binary encoding of timestamp.报错原因PostgreSql默认使用二进制进行数据的传输,导致的jdbc解析失败。解决方案数据库连接信息中配置不使用二进制传输 binaryTransfer=falsejdbc:postgresql://localhost:5432/test?binaryTransfer=false
2024年08月24日
235 阅读
1 评论
2024-07-31
代码实现:微博图片转存AList
最近想把之前我存在微博的图片转入 AList 中,发现有点问题,原因是微博开启防盗链,无法直接在浏览器中打开或直接拿到文件流,这就造成 AList 无法通过离线下载。原因分析微博图床开启防盗链,所以需要在请求头中携带 Referer ,这样才能获取到流数据。AList 也提供了三方接口,可以自己调用上传文件。详见:AList API文档代码实现上面的常量配置自己的 Alist 信息就可以了,主要是 域名、账号、密码以及上传路径package com.yanqingshan.blog; import cn.hutool.http.ContentType; import cn.hutool.http.Header; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; import cn.hutool.json.JSONUtil; import java.util.HashMap; import java.util.Map; /** * 微博上传Alist简单测试 * * @author yanqs * @since 2024-07-31 */ public class WeiBoImgDemo { /** * USER_AGENT */ private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"; /** * Alist 域名 */ private static final String BASE_URL = ""; /** * Alist 账号 */ private static final String USER_NAME = ""; /** * Alist 密码 */ private static final String PASSWORD = ""; /** * Alist 上传路径 */ private static final String UPLOAD_Path = ""; public static void main(String[] args) { String url = "https://tvax3.sinaimg.cn/large/a5286dc9ly1hs78a2y4scj22xs4eonpf.jpg"; int lastSlashIndex = url.lastIndexOf('/'); // 如果找到了斜杠,就从斜杠后面截取字符串 String fileName = url.substring(lastSlashIndex + 1); System.out.println("File Name: " + fileName); HttpRequest request = HttpRequest.get(url) .header(Header.REFERER, "https://weibo.com/")//头信息,多个头信息多次调用此方法即可 .header(Header.USER_AGENT, USER_AGENT) .timeout(20000); HttpResponse httpResponse = request.executeAsync(); // 获取到文件流 上传到Alist byte[] bytes = httpResponse.bodyBytes(); String result = HttpRequest.put(BASE_URL + "/api/fs/put") .header(Header.AUTHORIZATION, getToken()) .header(Header.CONTENT_TYPE, ContentType.MULTIPART.getValue()) .header("File-Path", UPLOAD_Path + fileName) .body(bytes) .execute().body(); System.out.println(result); } /** * 获取Alist Token * * @return */ public static String getToken() { Map<String, String> params = new HashMap<>(); params.put("username", USER_NAME); params.put("password", PASSWORD); String body = HttpRequest.post(BASE_URL + "/api/auth/login") .header(Header.CONTENT_TYPE, ContentType.JSON.getValue()) .body(JSONUtil.toJsonStr(params)) .execute().body(); return JSONUtil.parseObj(body).getJSONObject("data").getStr("token"); } }注:其中微博图片的链接有多种可选large -> 原始图片oslarge ->无水印 mw690 -> 最大 690 像素宽度裁剪thumbnail -> 缩略图small -> 小图square -> 80 像素正方形裁剪thumb150 -> 150 像素正方形裁剪thumb180 -> 180 像素正方形裁剪thumb300 -> 300 像素正方形裁剪orj180 -> 180 像素宽度原比例缩放orj360 -> 360 像素宽度原比例缩放运行结果运行效果如下后续可以自己建一个txt文件,将微博图片的后缀存起来,然后把上面代码改造一下就可以实现。
2024年07月31日
671 阅读
8 评论
2024-07-18
PostgreSQL:canceling statement due to statement timeout异常处理
某SQL语句执行超时,返回如下报错信息:当语句执行时间超过statement_timeout参数设置的时间时,该语句将会报错并退出执行。
2024年07月18日
292 阅读
0 评论
2023-11-17
VuePress 配置51LA/统计鸟统计代码
自从 语雀 付费和异常后,我也急需一款 Wiki知识手册 ,考虑了Hexo、GitBook、Docsify 等,感觉都各自有优缺点,最后选择了VuePress 2.0.0 搭建属于自己的私有化 Wiki知识手册 。使用过程中都还比较顺利,但是突然间发现跟其他 Vue 项目有点不太一样,少了一个 index.html ,这样不能在全局文件中引用/配置统计代码,刚好晚上在写知识手册的时候,看了一眼官方的说明文档,然后分享了一下统计代码,终于配置出来了。在全局 config.js 配置文件 head 参数中添加,就最终渲染出的 HTML 的 <head> 标签内加入的额外标签。但是之前一直添加不成功,后来分析了一下参数,这里以51LA为例。图上标注的红色就相当于红和绿就相当于第二个参数 { attrName: attrValue } ,而黄色就相当于最后一个参数 innerHTML? 那这样分析后,我们就可以这样写。head: [ ['script',{type:'text/javascript',src:'https://api.tongjiniao.com/c?_=***',async:''}], ['script',{charset:'UTF-8',id:'LA_COLLECT',src:'https://sdk.51.la/js-sdk-pro.min.js'}], ['script',{},'LA.init({id:"*****",ck:"*****",autoTrack:true,hashMode:true})'], ['script',{src: 'https://sdk.51.la/perf/js-sdk-perf.min.js',crossorigin:'anonymous'}], ['script',{},'new LingQue.Monitor().init({id:"******",sendSuspicious:true,sendSpaPv:true});'] ]第一个数组是统计鸟的,第二三数组是51LA的,第三四数组是51LA灵雀应用监控平台的。(注:其中官方的参数均使用**代替)至此,统计代码就安装完成了,如果要在 head 中引用其他脚本,也可以参考这样的写法。
2023年11月17日
629 阅读
2 评论
2023-08-29
SpringBoot 对接华为大数据平台kerberos认证的Kafka数据
最近项目中有用到kafka来同步某业务核心数据,通过kafka来进行数据的实时更新。原本使用的是Apache kafka 来进行订阅消费,后因业务方信创要求,更换了华为大数据平台的Kafka数据源,采用kerberos认证。对接了一天多,数据才接入成功,网上相关文档比较少,这里我总结一下,为后人少踩坑。本次使用的是华为MRS3.1.2版本,其他版本应该都类似。修改项目中的pom.xml依赖,将默认的apache的kafka-client包替换为华为自带的。如果拉去不到相关依赖包,请更换为华为Maven镜像,配置信息如下。<repositories> <repository> <id>huawei-cloud-sdk</id> <name>HuaWei Cloud Mirrors</name> <url>https://mirrors.huaweicloud.com/repository/maven/huaweicloudsdk/</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </repository> <repository> <id>huawei-mirrors</id> <name>HuaWei Mirrors</name> <url>https://repo.huaweicloud.com/repository/maven/</url> </repository> </repositories>我们需要在配置文件中增加新的配置文件,不要使用spring.kafka相关配置,建议自己新增一个配置信息,本文以huawei.mrs.kafka为例。huawei: mrs: kafka: enable: false bootstrap-servers: 10.244.231.2:21007,10.244.230.202:21007,10.244.230.125:21007 security: protocol: SASL_PLAINTEXT kerberos: domain: name: hadoop.hadoop_651_arm.com sasl: kerberos: service: name: kafka新建一个配置文件HuaWeiMrsKafkaConfiguration,配置相关信息@Value("${huawei.mrs.kafka.enable}") public Boolean enable; @Value("${huawei.mrs.kafka.bootstrap-servers}") public String boostrapServers; @Value("${huawei.mrs.kafka.security.protocol}") public String securityProtocol; @Value("${huawei.mrs.kafka.kerberos.domain.name}") public String kerberosDomainName; @Value("${huawei.mrs.kafka.sasl.kerberos.service.name}") public String kerberosServiceName; @Bean public ConcurrentKafkaListenerContainerFactory<?, ?> kafkaListenerContainerFactory( ConcurrentKafkaListenerContainerFactoryConfigurer configurer, ConsumerFactory<Object, Object> kafkaConsumerFactory, KafkaTemplate<String, String> template) { ConcurrentKafkaListenerContainerFactory<Object, Object> factory = new ConcurrentKafkaListenerContainerFactory<>(); configurer.configure(factory, kafkaConsumerFactory); //禁止消费者自启动,达到动态启动消费者的目的 factory.setAutoStartup(enable); return factory; } @Bean public ConsumerFactory<Object, Object> consumerFactory() { Map<String, Object> configs = new HashMap<>(); configs.put("security.protocol", securityProtocol); configs.put("kerberos.domain.name", kerberosDomainName); configs.put("bootstrap.servers", boostrapServers); configs.put("sasl.kerberos.service.name", kerberosServiceName); configs.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); configs.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); return new DefaultKafkaConsumerFactory<>(configs); } @Bean public KafkaTemplate<String, String> kafkaTemplate() { Map<String, Object> configs = new HashMap<>(); configs.put("security.protocol", securityProtocol); configs.put("kerberos.domain.name", kerberosDomainName); configs.put("bootstrap.servers", boostrapServers); configs.put("sasl.kerberos.service.name", kerberosServiceName); configs.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer"); configs.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer"); ProducerFactory<String, String> producerFactory = new DefaultKafkaProducerFactory<>(configs); return new KafkaTemplate<>(producerFactory); } @Bean public RecordMessageConverter converter() { return new StringJsonMessageConverter(); }再新建一个全局消费kafka数据的KafkaConsumer类@Slf4j @Component public class KafkaConsumer { @KafkaListener(topics = "topic1") public void topicMessage(ConsumerRecord<?, ?> record) { log.info("Kafka->topic:‘topic1’-->{}", record.value()); //TODO:业务逻辑 } }配置kerberos信息,也是非常重要的一步,配置kerberos认证文件,本文将以最简单的教程为例,在启动脚本中配置。为什么不在项目中配置呢?因为各位的项目都各自不同,放在resources目录中,有的时候会读取不到,所以我们以最简单的例子来作为讲解。打包项目,将打包好的jar放置在服务器中。并将下载安全集群认证用户的krb5.conf和user.keytab文件放置跟jar包相同目录或者自定义一个目录(本文以/data/java/huawei-mrs-kafka为例)。在这个文件夹或者部署目录通缉新建一个jaas.conf文件,将keyTab项修改为绝对路径。principal则是华为大数据平台提供的账号。Client { com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true keyTab="/data/java/huawei-mrs-kafka/user.keytab" principal="developuser@HADOOP_651_ARM.COM" useTicketCache=false storeKey=true debug=true; }; KafkaClient { com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true keyTab="/data/java/huawei-mrs-kafka/user.keytab" principal="developuser@HADOOP_651_ARM.COM" useTicketCache=false storeKey=true debug=true; }; 最后一步,运行jar包,指定krb5.conf和jaas.conf环境变量。java -jar -Djava.security.krb5.conf=/data/java/huawei-mrs-kafka/krb5.conf -Djava.security.auth.login.config=/data/java/huawei-mrs-kafka/jaas.conf huawei-mrs-kafka-1.0-SNAPSHOT.jar因为本地没有相关环境,生产环境又处于内网,这里就不提供相关运行成功的代码,对接华为大数据平台的Kafka其实很简单,只是网上的教程很少而已。如有这方面的问题,可以在本文留言,看到了就会回复。{cloud title="示例下载" type="default" url="https://www.gitlink.org.cn/yanqs/huawei-mrs-kafka-demo" password=""/}
2023年08月29日
651 阅读
0 评论
2023-08-10
使用VuePress搭建Wiki静态网站
最近使用 语雀 做了一个知识手册,改版后只能会员才能分享,想着数据托管到第三方,还不如自建。参考了其他静态网站生成,最后决定使用 VuePress 来搭建。环境要求Node.js v16.19.0+搭建框架步骤 1: 创建并进入一个新目录mkdir wiki-book cd wiki-book步骤 2: 初始化项目npm init步骤 3: 将 VuePress 安装为本地依赖npm install -D vuepress@next步骤 4: 在 package.json 中添加一些 scripts{ "scripts": { "docs:dev": "vuepress dev docs", "docs:build": "vuepress build docs" } }步骤 5: 将默认的临时目录和缓存目录添加到 .gitignore 文件中echo 'node_modules' >> .gitignore echo '.temp' >> .gitignore echo '.cache' >> .gitignore步骤 6: 创建你的第一篇文档mkdir docs echo '# Hello VuePress' > docs/README.md步骤 7: 在本地启动服务器来开发你的文档网站npm run docs:devVuePress 会在 http://localhost:8080 启动一个热重载的开发服务器。当你修改你的 Markdown 文件时,浏览器中的内容也会自动更新。进阶配置启动上面项目后,会在docs 下会生成一个.vuepress 目录,我们在这个目录下创建一个config.js 文件。这个是 VuePress 站点的基本配置文件,在这个里面我们可以配置站点基础信息、插件、主题等。具体可以参考官方文档:配置信息这里我把常用的配置分享一下:import { defineUserConfig } from 'vuepress' //引入默认主题 import { defaultTheme } from '@vuepress/theme-default' export default defineUserConfig({ // 开发服务器的端口号 port: 8080, // 启动后打开浏览器 open: false, // 设置站点根路径 base: '/', // 站点的语言 lang: 'zh-CN', // 站点的标题 title: '知识手册', // 站点的描述 description: '站点的描述', // 默认主题配置 theme: defaultTheme({ // 默认颜色模式 colorMode: 'auto', // 是否启用切换颜色模式的功能 colorModeSwitch: true, // logo Logo 图片的 URL。 //logo: '' // 导航栏配置 navbar:[ ], // 侧边栏配置 sidebar:[ ] }) })打包配置运行 npm run docs:build 生成后的文件在 docs\.vuepress\dist 中,将这个文件压缩丢在服务器中,就可以打开了。一般只要支持 html 的web服务器都是可以的。这里不做过多描述。样例代码{cloud title="样例代码" type="lz" url="https://xiaose.lanzoum.com/b02ewqy8h" password="h39g"/}
2023年08月10日
392 阅读
2 评论
1
2
...
5