Skip to content

Commit

Permalink
refactor: Say goodbye to adminPassword
Browse files Browse the repository at this point in the history
  • Loading branch information
cubewhy committed Oct 4, 2024
1 parent c004ca2 commit e75f9b8
Show file tree
Hide file tree
Showing 51 changed files with 363 additions and 523 deletions.
9 changes: 5 additions & 4 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ repositories {
}

dependencies {
implementation("cn.hutool:hutool-crypto:5.8.32")
implementation("cn.hutool:hutool-core:5.8.32")
implementation("com.bol:spring-data-mongodb-encrypt:2.9.1")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
implementation("com.alibaba.fastjson2:fastjson2:2.0.53")
implementation("com.alibaba.fastjson2:fastjson2-extension-spring6:2.0.53")
Expand All @@ -31,15 +32,15 @@ dependencies {
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.thymeleaf.extras:thymeleaf-extras-springsecurity6")
implementation("org.springframework.boot:spring-boot-starter-cache")
implementation("org.liquibase:liquibase-core")
implementation("org.springframework.session:spring-session-data-redis")
implementation("org.springframework.boot:spring-boot-starter-data-mongodb")
testImplementation("org.springframework.security:spring-security-test")
annotationProcessor("org.projectlombok:lombok")
implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
implementation("org.springframework.boot:spring-boot-starter-jdbc")
testImplementation("org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.3")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("io.projectreactor:reactor-test")
runtimeOnly("com.h2database:h2")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}
dependencyManagement {
Expand Down
15 changes: 0 additions & 15 deletions src/main/java/fuck/manthe/nmsl/annotation/Encrypted.java

This file was deleted.

13 changes: 6 additions & 7 deletions src/main/java/fuck/manthe/nmsl/config/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,15 @@ public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((conf) -> conf
.authorizeHttpRequests(conf -> conf
.requestMatchers("/dashboard**").authenticated()
.requestMatchers("/admin/**").hasRole("ADMIN")
.requestMatchers("/admin/**").hasAuthority("ADMIN")
.anyRequest().permitAll()
)
// .formLogin((form) -> form
// .loginPage("/dashboard/login")
// .loginProcessingUrl("/dashboard/login")
// .permitAll()
// )
.formLogin((form) -> form
.loginPage("/login")
.permitAll()
)
.formLogin(AbstractAuthenticationFilterConfigurer::permitAll)
.csrf(AbstractHttpConfigurer::disable)
.logout(LogoutConfigurer::permitAll);
Expand Down
23 changes: 13 additions & 10 deletions src/main/java/fuck/manthe/nmsl/controller/AuthController.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package fuck.manthe.nmsl.controller;

import cn.hutool.crypto.SecureUtil;
import com.standardwebhooks.exceptions.WebhookSigningException;
import fuck.manthe.nmsl.entity.*;
import fuck.manthe.nmsl.entity.dto.VapeAuthorizeDTO;
Expand All @@ -18,6 +17,7 @@
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import java.net.URLDecoder;
Expand All @@ -33,7 +33,7 @@ public class AuthController {
RedisTemplate<String, Long> redisTemplate;

@Resource
CrackedUserService crackedUserService;
UserService userService;

@Resource
RedeemService redeemService;
Expand All @@ -56,6 +56,9 @@ public class AuthController {
@Resource
MaintenanceService maintenanceService;

@Resource
PasswordEncoder passwordEncoder;

@Value("${share.cold-down.global.enabled}")
boolean coldDownEnabled;

Expand All @@ -77,18 +80,18 @@ public String auth(HttpServletRequest request) throws Exception {
String password = map.get("password");
// 统计请求次数
log.info("User {} login", username);
CrackedUser crackedUser = crackedUserService.findByUsername(username);
User crackedUser = userService.findByUsername(username);
if (maintenanceService.isMaintaining() && crackedUser.getExpire() != -1) {
// 暂停注入
log.info("Blocked user {} to inject. Injections are only open to lifetime users. (Maintaining)", username);
return ErrorCode.SERVER.formatError("Maintaining");
}
analysisService.authRequested(username);
if (!crackedUserService.isValid(username, password)) {
if (!userService.isValid(username, password)) {
// 凭证错误
return ErrorCode.ACCOUNT.formatError("Unauthorized");
}
if (crackedUserService.hasExpired(username)) {
if (userService.hasExpired(username)) {
// 账户失效
return ErrorCode.ACCOUNT.formatError("Expired");
}
Expand Down Expand Up @@ -161,7 +164,7 @@ public ResponseEntity<RestBean<String>> redeem(@RequestParam String username, @R
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(RestBean.failure(401, "Code was redeemed"));
}

if (crackedUserService.addUser(CrackedUser.builder().password(SecureUtil.sha1(password)).username(username).expire(expire).build())) {
if (userService.addUser(User.builder().password(passwordEncoder.encode(password)).username(username).expire(expire).build())) {
if (redeemService.useCode(redeemCode.getCode(), username)) {
log.info("User {} registered it's account with the code {} ({}d).", username, redeemCode.getCode(), redeemCode.getDate());
}
Expand All @@ -175,7 +178,7 @@ public ResponseEntity<RestBean<String>> redeem(@RequestParam String username, @R
webhookService.pushAll("renew", message);

return ResponseEntity.ok(RestBean.success("Registered."));
} else if (crackedUserService.isValid(username, password) && crackedUserService.renew(username, redeemCode.getDate())) {
} else if (userService.isValid(username, password) && userService.renew(username, redeemCode.getDate())) {
if (redeemService.useCode(redeemCode.getCode(), username)) {
log.info("User {} renewed it's account with the code {} ({}d).", username, redeemCode.getCode(), redeemCode.getDate());
}
Expand All @@ -184,7 +187,7 @@ public ResponseEntity<RestBean<String>> redeem(@RequestParam String username, @R
message.setRedeemUsername(username);
message.setTimestamp(System.currentTimeMillis() / 1000L);
message.setCode(redeemCode.getCode());
message.setExpireAt(crackedUserService.findByUsername(username).getExpire());
message.setExpireAt(userService.findByUsername(username).getExpire());
message.setContent("用户 %s 使用%s 兑换了%s 天订阅".formatted(username, redeemCode.getCode(), redeemCode.getDate()));
webhookService.pushAll("renew", message);
return ResponseEntity.ok(RestBean.success("Renewed."));
Expand All @@ -199,15 +202,15 @@ public String checkConnection() {

@GetMapping("verify")
public ResponseEntity<String> verify(@RequestParam String username, @RequestParam String password) {
if (!crackedUserService.isValid(username, password) || crackedUserService.hasExpired(username)) {
if (!userService.isValid(username, password) || userService.hasExpired(username)) {
return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
}
return ResponseEntity.ok("Valid user");
}

@PostMapping("verify")
public ResponseEntity<String> verify(@RequestBody VerifyLoginDTO dto) {
if (!crackedUserService.isValidHash(dto.getUsername(), dto.getHashedPassword()) || crackedUserService.hasExpired(dto.getUsername())) {
if (!userService.isValid(dto.getUsername(), dto.getPassword()) || userService.hasExpired(dto.getUsername())) {
return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
}
return ResponseEntity.ok("Valid user");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import fuck.manthe.nmsl.entity.RestBean;
import fuck.manthe.nmsl.entity.dto.LoginDTO;
import fuck.manthe.nmsl.service.CrackedUserService;
import fuck.manthe.nmsl.service.QueueService;
import fuck.manthe.nmsl.service.UserService;
import jakarta.annotation.Resource;
import org.jetbrains.annotations.NotNull;
import org.springframework.http.HttpStatus;
Expand All @@ -16,14 +16,14 @@
@RequestMapping("colddown/queue")
public class QueueController {
@Resource
CrackedUserService crackedUserService;
UserService userService;

@Resource
QueueService queueService;

@PostMapping("join")
public @NotNull ResponseEntity<RestBean<String>> join(@RequestBody LoginDTO login) {
if (!crackedUserService.isValid(login.getUsername(), login.getPassword()))
if (!userService.isValid(login.getUsername(), login.getPassword()))
return new ResponseEntity<>(RestBean.unauthorized("Unauthorized"), HttpStatus.UNAUTHORIZED);
if (!queueService.join(login.getUsername()))
return new ResponseEntity<>(RestBean.failure(409, "You're always queued."), HttpStatus.CONFLICT);
Expand All @@ -39,7 +39,7 @@ public List<String> query() {
@DeleteMapping("quit")
public @NotNull ResponseEntity<RestBean<String>> quit(@RequestBody LoginDTO login) {
// 不想玩了可以直接取消名额.
if (!crackedUserService.isValid(login.getUsername(), login.getPassword()))
if (!userService.isValid(login.getUsername(), login.getPassword()))
return new ResponseEntity<>(RestBean.failure(403, "Unauthorized"), HttpStatus.UNAUTHORIZED);
queueService.quit(login.getUsername());
return ResponseEntity.ok(RestBean.success("Removed " + login.getUsername() + " from queue."));
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/fuck/manthe/nmsl/controller/WebController.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ public String register() {
return "redeem";
}

@GetMapping("login")
public String login() {
return "login";
}

@GetMapping("maintain")
public String maintain(@RequestParam(required = false) String redirect) {
if (!maintenanceService.isMaintaining()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package fuck.manthe.nmsl.controller.admin;

import cn.hutool.core.util.RandomUtil;
import fuck.manthe.nmsl.entity.User;
import fuck.manthe.nmsl.entity.dto.AnalysisDTO;
import fuck.manthe.nmsl.service.AnalysisService;
import fuck.manthe.nmsl.service.CrackedUserService;
import fuck.manthe.nmsl.service.UserService;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
Expand All @@ -17,14 +21,35 @@
@Log4j2
public class AdminController {
@Resource
CrackedUserService crackedUserService;
UserService userService;

@Resource
AnalysisService analysisService;

@Value("${share.user.auto-delete-expired}")
boolean autoDeleteExpired;

@Resource
private PasswordEncoder passwordEncoder;

@PostConstruct
public void init() {
if (userService.count() == 0) {
String password = RandomUtil.randomString(16);
log.warn("Admin account created");
log.warn("Username: admin");
log.warn("Password: {}", password);
log.info("Dashboard at /dashboard");
log.warn("Please keep the account information safe, you will not be able to see it again!");
userService.addUser(User.builder()
.username("admin")
.password(passwordEncoder.encode(password))
.role("ADMIN")
.expire(-1L)
.build());
}
}

@RequestMapping("ping")
public ResponseEntity<String> ping() {
return ResponseEntity.ok("Pong");
Expand All @@ -36,7 +61,7 @@ public AnalysisDTO analysis() {
.todayLaunch(analysisService.getTodayLaunch())
.totalLaunch(analysisService.getTotalLaunch())
.todayRegister(analysisService.getTodayRegister())
.currentUsers(crackedUserService.count())
.currentUsers(userService.count())
.build();
}

Expand All @@ -49,7 +74,7 @@ public String logSuper() {
@Scheduled(cron = "0 0 0 * * *")
public void autoJob() {
if (autoDeleteExpired) {
crackedUserService.removeExpired();
userService.removeExpired();
}
analysisService.reset();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public RestBean<String> add(@RequestBody GatewayDTO gateway) throws Exception {
}

@DeleteMapping("remove")
public ResponseEntity<RestBean<String>> remove(@RequestParam long id) {
public ResponseEntity<RestBean<String>> remove(@RequestParam String id) {
if (gatewayService.removeGateway(id)) {
return new ResponseEntity<>(RestBean.failure(404, "Gateway not found"), HttpStatus.NOT_FOUND);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
package fuck.manthe.nmsl.controller.admin;

import cn.hutool.crypto.SecureUtil;
import fuck.manthe.nmsl.entity.CrackedUser;
import fuck.manthe.nmsl.entity.RestBean;
import fuck.manthe.nmsl.entity.User;
import fuck.manthe.nmsl.entity.dto.AddUserDTO;
import fuck.manthe.nmsl.entity.dto.CrackedUserDTO;
import fuck.manthe.nmsl.entity.dto.RenewDTO;
import fuck.manthe.nmsl.entity.dto.ResetPasswordDTO;
import fuck.manthe.nmsl.entity.dto.UserDTO;
import fuck.manthe.nmsl.service.AnalysisService;
import fuck.manthe.nmsl.service.CrackedUserService;
import fuck.manthe.nmsl.service.UserService;
import jakarta.annotation.Resource;
import jakarta.transaction.Transactional;
import lombok.extern.log4j.Log4j2;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import java.util.List;
Expand All @@ -23,14 +22,17 @@
@RequestMapping("/admin/user")
public class UserManageController {
@Resource
CrackedUserService crackedUserService;
UserService userService;

@Resource
AnalysisService analysisService;

@Resource
PasswordEncoder passwordEncoder;

@GetMapping("list")
public List<CrackedUserDTO> listUsers() {
return crackedUserService.list().stream().map((user) -> CrackedUserDTO.builder()
public List<UserDTO> listUsers() {
return userService.list().stream().map((user) -> UserDTO.builder()
.id(user.getId())
.username(user.getUsername())
.expire(user.getExpire())
Expand All @@ -46,7 +48,7 @@ public ResponseEntity<RestBean<String>> addUser(@RequestBody AddUserDTO dto) {
if (dto.getDays() != -1) {
expire = System.currentTimeMillis() + (long) dto.getDays() * 24 * 60 * 60 * 1000;
}
if (crackedUserService.addUser(CrackedUser.builder().password(SecureUtil.sha1(dto.getPassword())).username(dto.getUsername()).expire(expire).build())) {
if (userService.addUser(User.builder().password(passwordEncoder.encode(dto.getPassword())).username(dto.getUsername()).expire(expire).build())) {
return ResponseEntity.ok(RestBean.success("OK"));
}
return new ResponseEntity<>(RestBean.failure(409, "Conflict"), HttpStatus.CONFLICT);
Expand All @@ -56,38 +58,37 @@ public ResponseEntity<RestBean<String>> addUser(@RequestBody AddUserDTO dto) {
@PostMapping("renew/{username}")
public ResponseEntity<RestBean<String>> renew(@PathVariable String username, @RequestBody RenewDTO dto) {
log.info("An admin renewed the expire date of user {} ({}d)", username, dto.getDays());
if (crackedUserService.renew(username, dto.getDays())) {
if (userService.renew(username, dto.getDays())) {
return ResponseEntity.ok(RestBean.success("OK"));
}
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}

@PostMapping("renewAll")
public ResponseEntity<RestBean<String>> renewAll(@RequestBody RenewDTO dto) {
crackedUserService.renewAll(dto.getDays());
userService.renewAll(dto.getDays());
return ResponseEntity.ok(RestBean.success("OK"));
}

@DeleteMapping("remove/{username}")
public RestBean<Object> removeUser(@PathVariable String username) {
log.info("An admin removed a user with name {}", username);
crackedUserService.removeUser(username);
userService.removeUser(username);
return RestBean.success();
}

@PostMapping("password/{username}/reset")
public ResponseEntity<RestBean<String>> resetPassword(@PathVariable String username, @RequestBody ResetPasswordDTO dto) {
log.info("An admin reset the password of user {}", username);
if (crackedUserService.resetPassword(username, dto.getPassword())) {
if (userService.resetPassword(username, dto.getPassword())) {
return ResponseEntity.ok(RestBean.success());
}
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}

@Transactional
@DeleteMapping("removeExpired")
public RestBean<String> removeExpired() {
crackedUserService.removeExpired();
userService.removeExpired();
return RestBean.success("Success");
}
}
Loading

0 comments on commit e75f9b8

Please sign in to comment.