gitee: NiterForum 흙손
시작
속성 파일 인코딩 문제 : (46개 메시지) Intellij IDEA 2018 속성 파일 유니코드를 중국어 settings_properties 파일\u6d4f\u89c8\u5668\u8868\u5355\u5185\u_Program 새 비전 블로그-CSDN 블로그
SSL 인증서 신청 및 다운로드 : 알리바바 클라우드 또는 텐센트 클라우드에서 SSL 인증서 서비스를 찾아 신청만 하면 됩니다. (사전 도메인 이름 신청 필요)
HTTPS를 사용하지 않는 경우 :
application.properties 수정
#http端口号 80
# server.custom.httpPort=80
#https加密端口号 443
server.port=80
#SSL证书路径 一定要加上classpath:
# server.ssl.key-store=classpath:niter_cn.jks
#SSL证书密码
# server.ssl.key-store-password=***
#证书类型
# server.ssl.key-store-type=JKS
cn/niter/forum/config/HttpsConfig.java
파일을 삭제하거나 그 안의 코드를 주석 처리하십시오.
다음 메타 태그를 제거하십시오 resources/templates/common/header.html
.
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
cn/niter/forum/util/CookieUtils.java
삭제
cookie.setHttpOnly(true);//通过js脚本是无法获取到cookie的信息的。防止XSS攻击。
맞춤 정보 :
사이트 정보, 메타 태그, 연락처 정보, 검색 엔진 검증 태그, 사용자 그룹 레벨 이름 및 상한 포인트, 포인트 이름 및 가중치, 사용자 행동 포인트 보상, 뉴스 상담 인터페이스(건너뛰기 가능), 사용자 정의 속성 파일의 제스처 검증 코드 서비스(VAPTCHA) ), SMS관련 상품, 텐센트 기업우편함(개인우편함 이용가능), 깃허브 로그인
사이트 정보:
#这项非常重要,请务必准确填写域名、ip或者localhost,不要加http(s)://,以及后面的/。
site.main.domain=localhost
인증코드 서비스는 https://www.vaptcha.com/에 접속하여 인증단위 생성 도메인명이 local인 경우 localhost 입력 후 속성에 VID, KEY 복사
#手势验证码vaptcha的vid与key,请去官网获取https://www.vaptcha.com/ 。也可以使用自己选用验证码服务,但需要修改源码!
vaptcha.vid=***
vaptcha.key=***
#腾讯企业邮箱相关配置信息,请去官网获取https://exmail.qq.com/ 。也可以使用自己的邮箱账号。修改成对应信息即可!
exmail.account=***
exmail.password=***
exmail.smtp.host=smtp.exmail.qq.com
깃허브 로그인
#github登录 API配置信息。请去这里创建应用即可,秒审核,轻松配置 https://github.com/settings/applications/new
github.client.id=***
github.client.secret=***
github.redirect.uri=http(s)://localhost/callback
바이두 로그인
#百度登录 API配置信息。请去这里创建应用即可,秒审核,轻松配置 http://developer.baidu.com/console#app/create
baidu.client.id=***
baidu.client.secret=***
baidu.redirect.uri=http(s)://localhost/callbackbaidu
웨이보 로그인
#微博登录 API配置信息。请去这里创建应用即可,审核需要域名,无需备案 https://open.weibo.com/apps/new?sort=web
weibo.client.id=***
weibo.client.secret=***
weibo.redirect.uri=http://localhost/callbackweibo
QQ 로그인
#QQ登录 API配置信息。请去这里创建应用即可,审核需要域名,如申请国际域名接入,无需备案 https://connect.qq.com/manage.html#/appcreate/web
qq.client.id=***
qq.client.secret=***
qq.redirect.uri=http(s)://yourdomain/callbackqq
데이터베이스 구성 수정 :
#数据库配置,填写你自己的
spring.datasource.url=jdbc:mysql://localhost:3306/***
spring.datasource.username=***
spring.datasource.password=***
#数据库配置2,按需修改。如不熟悉,不建议修改
spring.datasource.hikari.connection-init-sql=set names utf8mb4;
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.hikari.minimum-idle=3
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.max-lifetime =30000
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.type-aliases-package=cn.niter.forum.mapper
mybatis.mapper-locations=classpath:mapper/*.xml
/resource/generatorConfig.xml
수정 위치 :
<plugin type="org.mybatis.generator.plugins.RowBoundsPlugin"></plugin>
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/niter"
userId="***"
password="****">
</jdbcConnection>
객체 스토리지 구성:
#腾讯云账户设置
qcloud.secret-id=***
qcloud.secret-key=***
#是否开启关键字自动生成,enable默认为0关闭;改为1开启
qcloud.keywords.enable=0
#是否开启数据万象功能,enable默认为0关闭;改为1开启。该功能用于上传图片的审核、压缩(仅限jpg)、水印生成,也可用于头像的剪切
qcloud.ci.enable=0
#数据万象的访问域名,最后斜杠不能省
qcloud.ci.objecturl=https://qcdn2.niter.cn/
#腾讯云对象存储配置,修改成你自己的。也可以自选对象存储服务,但需要修改源码!
qcloud.cos.bucket-name=niter-1251590924
qcloud.cos.region=ap-nanjing
#这是你对象存储的访问域名,最后斜杠不能省。
qcloud.cos.objecturl=https://qcdn.niter.cn/
qcloud.sms.appId=1400000000
qcloud.sms.sign=尼特IT
qcloud.sms.tempId=200000
기타 구성:
#是否开启tinify png压缩功能,注意压缩需要时间等待,可配合压缩阈值根据需要开启关闭,默认0关闭,1开启
tinify.enable=0
#请于此处https://tinify.cn/developers 注册开发者账号,即可每月免费压缩500张,填写获取到的key
tinify.key=sadfdg
#压缩阈值,超过这个长度才压缩,否则不压缩,默认1M
tinify.minContentLength=1024000
#百度云内容审核 https://ai.baidu.com/tech/textcensoring
#是否开启内容审核自动生成,enable默认为0关闭;改为1开启
baiducloud.censor.enable=0
baiducloud.censor.appid=12345678
baiducloud.censor.apikey=***
baiducloud.censor.secretkey=***
#其它配置,按需修改,如不熟悉。不建议修改
logging.file=logs/community.log
logging.level.root=info
logging.file.max-history=15
logging.file.max-size=100MB
server.servlet.session.timeout=15552000
spring.mvc.favicon.enabled=false
spring.servlet.multipart.max-file-size=5MB
spring.servlet.multipart.max-request-size=10MB
spring:
thymeleaf:
cache: false
mode: LEGACYHTML5
#resource
# 启用缓存
spring.resources.chain.cache=true
# 资源缓存时间,单位秒-缓存7天
spring.resources.cache.period=604800
오류 수정 :
cn.niter.forum.provider.QCloudProvider
에서 :
// import sun.misc.BASE64Encoder;
import org.apache.commons.codec.binary.Base64;
// String encodeBase64 = new BASE64Encoder().encode(data);
String encodeBase64 = Base64.encodeBase64String(data);
프로젝트에서 64비트 인코딩으로 설계합니다. 때때로 개발은 JDK와 함께 제공되는 BASE64 도구를 사용합니다 . 그러나 썬컴퍼니는 그렇게 하지 않는 것이 좋습니다. 특히 JDK 버전이 업데이트되면 프로젝트에 저장된 정보까지 포함됩니다. 교체를 위해 import org.apache.commons.codec.binary.Base64를 참조할 수 있습니다.
mysql은 버전 5를 사용합니다.
페이지의 js는 비엔티안 데이터를 요청하는 워터마크 서비스로 작성되었습니다. 활성화되지 않은 경우 잘못된 요청 경로가 전송됩니다.
https://.../upload/user/2/img/20230403174530_gh.jpeg # 没开启,正确
https://.../upload/user/2/img/20230403174530_gh.jpeg/water_mark # 没开启,错误
수정 /resource/templates/t/index.html
:
// str = str + "<img data-id=" + item.id + " layer-src=\"" + item.imageUrls[j] + "/watermark_text\" src=\"" + item.imageUrls[j] + "/t_small\">";
str = str + "<img data-id=" + item.id + " layer-src=\"" + item.imageUrls[j] + "\" src=\"" + item.imageUrls[j] + "\">";
로그인
홈페이지 방문
먼저 IndexController.forum 메서드를 입력합니다.
로그인 상태 확인, 상위 질문 및 질문 목록 처리, 인기 태그 및 등록 사용자 사용 캐시(목록)
로그인-정보입력-인간-기계검증 클릭 후 ValidateController#post 메소드('/validate', post)를 통과 후 입력합니다. 게시 방법, 액세스 토큰 제출, 장면, IP
여기서 ExpiringMap
맵 .
ExpiringMap<String,String> interval = ExpiringMap.builder() // 存ip, token
.maxSize(20)//设置最大容量,增大攻击难度,值越大存储的可疑ip越多,过大会占用额外资源
.expiration(30, TimeUnit.SECONDS)//过期时间30秒
.expirationPolicy(ExpirationPolicy.CREATED)//每次访问重置过期时间
.variableExpiration()
.build();
ExpiringMap<String,Integer> ipScores = ExpiringMap.builder() // 存ip, scene
.maxSize(100)//设置最大容量,增大攻击难度,值越大存储的可疑ip越多,过大会占用额外资源
.expiration(1, TimeUnit.DAYS)//过期时间1天
.expirationPolicy(ExpirationPolicy.CREATED)//每次更新重置过期时间
.variableExpiration()
.build();
ExpiringMap 함수:
1. 지도의 항목은 일정 기간 후에 자동으로 만료되도록 설정할 수 있습니다.
2. Map의 최대 용량 값을 설정할 수 있으며 최대 크기에 도달했을 때 값을 다시 삽입하면 Map의 첫 번째 값이 만료됩니다.
3. 청취 이벤트를 추가하고 항목이 만료되면 청취 기능을 예약할 수 있습니다.
4. get() 메서드 호출 시 객체를 생성하도록 지연 로딩을 설정할 수 있습니다.
그런 다음 두 번째 인간-기계 검증을 VaptchaProvider.getValidateResult(token,scene,ip)
수행하는 데
Ctrl + Alt + H 를 UserService.registerOrLoginWithMail
사용 메서드 호출 체인을 보고, SsoApi.registerOrLoginWithMail 호출을 찾고, 이 클래스에서 '/login' 요청에 대한 매핑 메서드 로그인을 찾습니다.
요점은 다음과 같습니다. selectByExample 사용
(48 메시지) 일반적으로 selectByExample 사용 Mapper_ccity86155의 블로그-CSDN 블로그
/*
Example 查询范例
Criteria 查询标准,Example的静态内部类
*/
Example example=new Example(要查询的表对应的实体类.class);
Example.Criteria criteria=example.createCriteria();//创建查询标准
criteria.andEqualTo("字段","值");//调用方法,编写自己想要查询的条件
List list=userMapper.selectByExample(example);
List list=userMapper.selectByExampleAndRowBounds(example,new RowBounds(0,2));// 指定获取几条特定的查询语句,类似于limit。可以在分页的时候使用
그리고 JWT :
resultDTO.setData(tokenUtils.getToken(getUserDTO(users.get(0))));
-----------------^
|
public String getToken(UserDTO user) {
String token = "";
token = JWT.create()
.withIssuer("NiterUser")
//.withAudience(""+user.getId())// 将 user id 保存到 token 里面
.withClaim("name", user.getName())
.withClaim("id",user.getId())
//.withClaim("userId",""+user.getId())
.withClaim("avatarUrl",user.getAvatarUrl())
.withClaim("groupId",user.getGroupId())
.withClaim("vipRank",user.getVipRank())
.withExpiresAt(new Date(System.currentTimeMillis() + 3600000 * 24 * 3))//三天
.sign(Algorithm.HMAC256(SECRET));// 以 password 作为 token 的签名/密钥
return token;
}
인터셉터(AOP 프로그래밍, 인터셉트 "/**")에는 토큰을 확인하기 위한 다음 코드가 있습니다.
HandlerMethod handlerMethod=(HandlerMethod)handler;
Method method=handlerMethod.getMethod();
String token=null;
ResultDTO resultDTO=null;
Cookie[] cookies = request.getCookies();
boolean hashToken = false;
if(cookies!=null&&cookies.length!=0){
for (Cookie cookie : cookies) {
if(cookie.getName().equals("token")){
token=cookie.getValue(); // 获取cookie里的tocken
if(token!=null) {
hashToken=true; // 标记tocken有值
resultDTO = tokenUtils.verifyToken(token); // 验证tocken
if(resultDTO.getCode()==200){
// 成功
UserDTO userDTO = (UserDTO) resultDTO.getData();
request.setAttribute("loginUser",userDTO);
loginUserCache.putLoginUser(userDTO.getId(),
System.currentTimeMillis());//写入loginCache
}
}
break;
}
}
}
if (method.isAnnotationPresent(UserLoginToken.class)) {
//如果请求的映射方法有自定义注解
UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);
if (userLoginToken.required()) {
// 注解的required属性为true(需要认证)
// 执行认证
if ((!hashToken)||resultDTO.getCode()!=200) {
throw new CustomizeException(CustomizeErrorCode.NO_LOGIN);
}
}
}
// 自定义注解
@Target({
ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserLoginToken {
boolean required() default true;
}
자세한 내용은 JWT 상세 튜토리얼 및 Use_jwt Tutorial_이상적인 달새가 있는 블로그를 참조하세요.
그런 다음 홈페이지로 이동하여 홈페이지 게시물 표시 및 사용자 메시지 프롬프트(""/api/notification/mine" 요청)를 처리합니다.