From ba6ab4b1ee8e0e0b3ba5222da565723fdeee4e9c Mon Sep 17 00:00:00 2001 From: Bunny <1319900154@qq.com> Date: Fri, 11 Jul 2025 13:48:10 +0800 Subject: [PATCH] =?UTF-8?q?:tada:=20init-=E9=98=B6=E6=AE=B5=E4=BA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{security => }/impl/LoginServiceImpl.java | 2 +- spring-security/pom.xml | 3 +- .../{security => }/impl/LoginServiceImpl.java | 2 +- spring-security/step-2/ReadMe.md | 0 spring-security/step-2/pom.xml | 27 + .../SpringSecurityStep1Application.java | 11 + .../com/spring/bean/dto/LoginRequest.java | 22 + .../java/com/spring/bean/vo/package-info.java | 1 + .../com/spring/bean/vo/result/PageResult.java | 34 ++ .../com/spring/bean/vo/result/Result.java | 173 ++++++ .../spring/bean/vo/result/ResultCodeEnum.java | 90 ++++ .../java/com/spring/config/Knife4jConfig.java | 49 ++ .../spring/controller/CheckController.java | 23 + .../spring/controller/LoginController.java | 18 + .../config/SecurityConfiguration.java | 65 +++ .../config/SecurityWebConfiguration.java | 65 +++ .../handler/SecurityAccessDeniedHandler.java | 28 + .../SecurityAuthenticationEntryPoint.java | 29 + .../security/password/MD5PasswordEncoder.java | 52 ++ .../service/CustomUserDetailsService.java | 35 ++ .../java/com/spring/service/LoginService.java | 4 + .../spring/service/impl/LoginServiceImpl.java | 11 + .../src/main/resources/application-dev.yml | 7 + .../step-2/src/main/resources/application.yml | 34 ++ .../step-2/src/main/resources/banner.txt | 11 + .../step-2/src/main/resources/logback.xml | 72 +++ .../src/main/resources/static/css/css2.css | 108 ++++ .../src/main/resources/static/error/400.html | 69 +++ .../src/main/resources/static/error/403.html | 69 +++ .../src/main/resources/static/error/404.html | 78 +++ .../src/main/resources/static/error/500.html | 64 +++ .../src/main/resources/static/error/501.html | 66 +++ .../src/main/resources/static/error/502.html | 80 +++ .../src/main/resources/static/error/503.html | 69 +++ .../src/main/resources/static/error/504.html | 81 +++ .../src/main/resources/static/error/505.html | 72 +++ .../src/main/resources/static/error/506.html | 66 +++ .../src/main/resources/static/error/507.html | 66 +++ .../src/main/resources/static/error/509.html | 66 +++ .../src/main/resources/static/error/510.html | 66 +++ .../src/main/resources/static/favicon.ico | Bin 0 -> 17014 bytes .../src/main/resources/templates/index.html | 503 ++++++++++++++++++ .../src/main/resources/templates/login.html | 206 +++++++ 43 files changed, 2594 insertions(+), 3 deletions(-) rename spring-security/official/src/main/java/com/spring/service/{security => }/impl/LoginServiceImpl.java (84%) rename spring-security/step-1/src/main/java/com/spring/service/{security => }/impl/LoginServiceImpl.java (84%) create mode 100644 spring-security/step-2/ReadMe.md create mode 100644 spring-security/step-2/pom.xml create mode 100644 spring-security/step-2/src/main/java/com/spring/SpringSecurityStep1Application.java create mode 100644 spring-security/step-2/src/main/java/com/spring/bean/dto/LoginRequest.java create mode 100644 spring-security/step-2/src/main/java/com/spring/bean/vo/package-info.java create mode 100644 spring-security/step-2/src/main/java/com/spring/bean/vo/result/PageResult.java create mode 100644 spring-security/step-2/src/main/java/com/spring/bean/vo/result/Result.java create mode 100644 spring-security/step-2/src/main/java/com/spring/bean/vo/result/ResultCodeEnum.java create mode 100644 spring-security/step-2/src/main/java/com/spring/config/Knife4jConfig.java create mode 100644 spring-security/step-2/src/main/java/com/spring/controller/CheckController.java create mode 100644 spring-security/step-2/src/main/java/com/spring/controller/LoginController.java create mode 100644 spring-security/step-2/src/main/java/com/spring/security/config/SecurityConfiguration.java create mode 100644 spring-security/step-2/src/main/java/com/spring/security/config/SecurityWebConfiguration.java create mode 100644 spring-security/step-2/src/main/java/com/spring/security/handler/SecurityAccessDeniedHandler.java create mode 100644 spring-security/step-2/src/main/java/com/spring/security/handler/SecurityAuthenticationEntryPoint.java create mode 100644 spring-security/step-2/src/main/java/com/spring/security/password/MD5PasswordEncoder.java create mode 100644 spring-security/step-2/src/main/java/com/spring/security/service/CustomUserDetailsService.java create mode 100644 spring-security/step-2/src/main/java/com/spring/service/LoginService.java create mode 100644 spring-security/step-2/src/main/java/com/spring/service/impl/LoginServiceImpl.java create mode 100644 spring-security/step-2/src/main/resources/application-dev.yml create mode 100644 spring-security/step-2/src/main/resources/application.yml create mode 100644 spring-security/step-2/src/main/resources/banner.txt create mode 100644 spring-security/step-2/src/main/resources/logback.xml create mode 100644 spring-security/step-2/src/main/resources/static/css/css2.css create mode 100644 spring-security/step-2/src/main/resources/static/error/400.html create mode 100644 spring-security/step-2/src/main/resources/static/error/403.html create mode 100644 spring-security/step-2/src/main/resources/static/error/404.html create mode 100644 spring-security/step-2/src/main/resources/static/error/500.html create mode 100644 spring-security/step-2/src/main/resources/static/error/501.html create mode 100644 spring-security/step-2/src/main/resources/static/error/502.html create mode 100644 spring-security/step-2/src/main/resources/static/error/503.html create mode 100644 spring-security/step-2/src/main/resources/static/error/504.html create mode 100644 spring-security/step-2/src/main/resources/static/error/505.html create mode 100644 spring-security/step-2/src/main/resources/static/error/506.html create mode 100644 spring-security/step-2/src/main/resources/static/error/507.html create mode 100644 spring-security/step-2/src/main/resources/static/error/509.html create mode 100644 spring-security/step-2/src/main/resources/static/error/510.html create mode 100644 spring-security/step-2/src/main/resources/static/favicon.ico create mode 100644 spring-security/step-2/src/main/resources/templates/index.html create mode 100644 spring-security/step-2/src/main/resources/templates/login.html diff --git a/spring-security/official/src/main/java/com/spring/service/security/impl/LoginServiceImpl.java b/spring-security/official/src/main/java/com/spring/service/impl/LoginServiceImpl.java similarity index 84% rename from spring-security/official/src/main/java/com/spring/service/security/impl/LoginServiceImpl.java rename to spring-security/official/src/main/java/com/spring/service/impl/LoginServiceImpl.java index 649e7ae..c7c96e7 100644 --- a/spring-security/official/src/main/java/com/spring/service/security/impl/LoginServiceImpl.java +++ b/spring-security/official/src/main/java/com/spring/service/impl/LoginServiceImpl.java @@ -1,4 +1,4 @@ -package com.spring.service.security.impl; +package com.spring.service.impl; import com.spring.service.security.LoginService; import lombok.RequiredArgsConstructor; diff --git a/spring-security/pom.xml b/spring-security/pom.xml index 4ac4735..e843813 100644 --- a/spring-security/pom.xml +++ b/spring-security/pom.xml @@ -20,8 +20,9 @@ official step-1 + step-2 - + UTF-8 17 diff --git a/spring-security/step-1/src/main/java/com/spring/service/security/impl/LoginServiceImpl.java b/spring-security/step-1/src/main/java/com/spring/service/impl/LoginServiceImpl.java similarity index 84% rename from spring-security/step-1/src/main/java/com/spring/service/security/impl/LoginServiceImpl.java rename to spring-security/step-1/src/main/java/com/spring/service/impl/LoginServiceImpl.java index 649e7ae..c7c96e7 100644 --- a/spring-security/step-1/src/main/java/com/spring/service/security/impl/LoginServiceImpl.java +++ b/spring-security/step-1/src/main/java/com/spring/service/impl/LoginServiceImpl.java @@ -1,4 +1,4 @@ -package com.spring.service.security.impl; +package com.spring.service.impl; import com.spring.service.security.LoginService; import lombok.RequiredArgsConstructor; diff --git a/spring-security/step-2/ReadMe.md b/spring-security/step-2/ReadMe.md new file mode 100644 index 0000000..e69de29 diff --git a/spring-security/step-2/pom.xml b/spring-security/step-2/pom.xml new file mode 100644 index 0000000..0eae0c1 --- /dev/null +++ b/spring-security/step-2/pom.xml @@ -0,0 +1,27 @@ + + 4.0.0 + + com.mall + spring-security + 0.0.1-SNAPSHOT + + + step-2 + 学习步骤1,不前后端分离的项目 + jar + + step-2 + https://maven.apache.org + + + UTF-8 + 17 + 17 + 17 + + + + + + diff --git a/spring-security/step-2/src/main/java/com/spring/SpringSecurityStep1Application.java b/spring-security/step-2/src/main/java/com/spring/SpringSecurityStep1Application.java new file mode 100644 index 0000000..d068ecb --- /dev/null +++ b/spring-security/step-2/src/main/java/com/spring/SpringSecurityStep1Application.java @@ -0,0 +1,11 @@ +package com.spring; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringSecurityStep1Application { + public static void main(String[] args) { + SpringApplication.run(SpringSecurityStep1Application.class, args); + } +} diff --git a/spring-security/step-2/src/main/java/com/spring/bean/dto/LoginRequest.java b/spring-security/step-2/src/main/java/com/spring/bean/dto/LoginRequest.java new file mode 100644 index 0000000..e50ae7d --- /dev/null +++ b/spring-security/step-2/src/main/java/com/spring/bean/dto/LoginRequest.java @@ -0,0 +1,22 @@ +package com.spring.bean.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "LoginRequest", title = "LoginRequest登录参数", description = "登录请求参数") +public class LoginRequest { + + @Schema(name = "username", title = "用户名") + private String username; + + @Schema(name = "password", description = "密码") + private String password; + +} diff --git a/spring-security/step-2/src/main/java/com/spring/bean/vo/package-info.java b/spring-security/step-2/src/main/java/com/spring/bean/vo/package-info.java new file mode 100644 index 0000000..970000e --- /dev/null +++ b/spring-security/step-2/src/main/java/com/spring/bean/vo/package-info.java @@ -0,0 +1 @@ +package com.spring.bean.vo; \ No newline at end of file diff --git a/spring-security/step-2/src/main/java/com/spring/bean/vo/result/PageResult.java b/spring-security/step-2/src/main/java/com/spring/bean/vo/result/PageResult.java new file mode 100644 index 0000000..2a63921 --- /dev/null +++ b/spring-security/step-2/src/main/java/com/spring/bean/vo/result/PageResult.java @@ -0,0 +1,34 @@ +package com.spring.bean.vo.result; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * 封装分页查询结果 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "PageResult 对象", title = "分页返回结果", description = "分页返回结果") +public class PageResult implements Serializable { + + @Schema(name = "pageNo", title = "当前页") + private Long pageNo; + + @Schema(name = "pageSize", title = "每页记录数") + private Long pageSize; + + @Schema(name = "total", title = "总记录数") + private Long total; + + @Schema(name = "list", title = "当前页数据集合") + private List list; + +} \ No newline at end of file diff --git a/spring-security/step-2/src/main/java/com/spring/bean/vo/result/Result.java b/spring-security/step-2/src/main/java/com/spring/bean/vo/result/Result.java new file mode 100644 index 0000000..546db04 --- /dev/null +++ b/spring-security/step-2/src/main/java/com/spring/bean/vo/result/Result.java @@ -0,0 +1,173 @@ +package com.spring.bean.vo.result; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class Result { + // 状态码 + private Integer code; + // 返回消息 + private String message; + // 返回数据 + private T data; + + /** + * * 自定义返回体 + * + * @param data 返回体 + * @return Result + */ + protected static Result build(T data) { + Result result = new Result<>(); + result.setData(data); + return result; + } + + /** + * * 自定义返回体,使用ResultCodeEnum构建 + * + * @param body 返回体 + * @param codeEnum 返回状态码 + * @return Result + */ + public static Result build(T body, ResultCodeEnum codeEnum) { + Result result = build(body); + result.setCode(codeEnum.getCode()); + result.setMessage(codeEnum.getMessage()); + return result; + } + + /** + * * 自定义返回体 + * + * @param body 返回体 + * @param code 返回状态码 + * @param message 返回消息 + * @return Result + */ + public static Result build(T body, Integer code, String message) { + Result result = build(body); + result.setCode(code); + result.setMessage(message); + result.setData(null); + return result; + } + + /** + * * 操作成功 + * + * @return Result + */ + public static Result success() { + return success(null, ResultCodeEnum.SUCCESS); + } + + /** + * * 操作成功 + * + * @param data baseCategory1List + */ + public static Result success(T data) { + return build(data, ResultCodeEnum.SUCCESS); + } + + /** + * * 操作成功-状态码 + * + * @param codeEnum 状态码 + */ + public static Result success(ResultCodeEnum codeEnum) { + return success(null, codeEnum); + } + + /** + * * 操作成功-自定义返回数据和状态码 + * + * @param data 返回体 + * @param codeEnum 状态码 + */ + public static Result success(T data, ResultCodeEnum codeEnum) { + return build(data, codeEnum); + } + + /** + * * 操作失败-自定义返回数据和状态码 + * + * @param data 返回体 + * @param message 错误信息 + */ + public static Result success(T data, String message) { + return build(data, 200, message); + } + + /** + * * 操作失败-自定义返回数据和状态码 + * + * @param data 返回体 + * @param code 状态码 + * @param message 错误信息 + */ + public static Result success(T data, Integer code, String message) { + return build(data, code, message); + } + + /** + * * 操作失败 + */ + public static Result error() { + return Result.build(null); + } + + /** + * * 操作失败-自定义返回数据 + * + * @param data 返回体 + */ + public static Result error(T data) { + return build(data, ResultCodeEnum.FAIL); + } + + /** + * * 操作失败-状态码 + * + * @param codeEnum 状态码 + */ + public static Result error(ResultCodeEnum codeEnum) { + return build(null, codeEnum); + } + + /** + * * 操作失败-自定义返回数据和状态码 + * + * @param data 返回体 + * @param codeEnum 状态码 + */ + public static Result error(T data, ResultCodeEnum codeEnum) { + return build(data, codeEnum); + } + + /** + * * 操作失败-自定义返回数据和状态码 + * + * @param data 返回体 + * @param code 状态码 + * @param message 错误信息 + */ + public static Result error(T data, Integer code, String message) { + return build(data, code, message); + } + + /** + * * 操作失败-自定义返回数据和状态码 + * + * @param data 返回体 + * @param message 错误信息 + */ + public static Result error(T data, String message) { + return build(null, 500, message); + } +} diff --git a/spring-security/step-2/src/main/java/com/spring/bean/vo/result/ResultCodeEnum.java b/spring-security/step-2/src/main/java/com/spring/bean/vo/result/ResultCodeEnum.java new file mode 100644 index 0000000..7ab3b98 --- /dev/null +++ b/spring-security/step-2/src/main/java/com/spring/bean/vo/result/ResultCodeEnum.java @@ -0,0 +1,90 @@ +package com.spring.bean.vo.result; + +import lombok.Getter; + +/** + * 统一返回结果状态信息类 + */ +@Getter +public enum ResultCodeEnum { + // 成功操作 200 + SUCCESS(200, "操作成功"), + LOAD_FINISHED(200, "加载完成"), + ADD_SUCCESS(200, "添加成功"), + UPDATE_SUCCESS(200, "修改成功"), + DELETE_SUCCESS(200, "删除成功"), + SORT_SUCCESS(200, "排序成功"), + SUCCESS_UPLOAD(200, "上传成功"), + SUCCESS_LOGOUT(200, "退出成功"), + EMAIL_CODE_REFRESH(200, "邮箱验证码已刷新"), + EMAIL_CODE_SEND_SUCCESS(200, "邮箱验证码已发送"), + + // 验证错误 201 + USERNAME_OR_PASSWORD_NOT_EMPTY(201, "用户名或密码不能为空"), + EMAIL_CODE_NOT_EMPTY(201, "邮箱验证码不能为空"), + SEND_EMAIL_CODE_NOT_EMPTY(201, "请先发送邮箱验证码"), + EMAIL_CODE_NOT_MATCHING(201, "邮箱验证码不匹配"), + LOGIN_ERROR(500, "账号或密码错误"), + LOGIN_ERROR_USERNAME_PASSWORD_NOT_EMPTY(201, "登录信息不能为空"), + GET_BUCKET_EXCEPTION(201, "获取文件信息失败"), + SEND_MAIL_CODE_ERROR(201, "邮件发送失败"), + EMAIL_CODE_EMPTY(201, "邮箱验证码过期或不存在"), + EMAIL_EXIST(201, "邮箱已存在"), + REQUEST_IS_EMPTY(201, "请求数据为空"), + DATA_TOO_LARGE(201, "请求数据为空"), + UPDATE_NEW_PASSWORD_SAME_AS_OLD_PASSWORD(201, "新密码与密码相同"), + + // 数据相关 206 + ILLEGAL_REQUEST(206, "非法请求"), + REPEAT_SUBMIT(206, "重复提交"), + DATA_ERROR(206, "数据异常"), + EMAIL_USER_TEMPLATE_IS_EMPTY(206, "邮件模板为空"), + EMAIL_TEMPLATE_IS_EMPTY(206, "邮件模板为空"), + EMAIL_USER_IS_EMPTY(206, "关联邮件用户配置为空"), + DATA_EXIST(206, "数据已存在"), + DATA_NOT_EXIST(206, "数据不存在"), + ALREADY_USER_EXCEPTION(206, "用户已存在"), + USER_IS_EMPTY(206, "用户不存在"), + FILE_NOT_EXIST(206, "文件不存在"), + NEW_PASSWORD_SAME_OLD_PASSWORD(206, "新密码不能和旧密码相同"), + MISSING_TEMPLATE_FILES(206, "缺少模板文件"), + + // 身份过期 208 + LOGIN_AUTH(208, "请先登陆"), + AUTHENTICATION_EXPIRED(208, "身份验证过期"), + SESSION_EXPIRATION(208, "会话过期"), + + // 209 + THE_SAME_USER_HAS_LOGGED_IN(209, "相同用户已登录"), + + // 提示错误 + UPDATE_ERROR(216, "修改失败"), + URL_ENCODE_ERROR(216, "URL编码失败"), + ILLEGAL_CALLBACK_REQUEST_ERROR(217, "非法回调请求"), + FETCH_USERINFO_ERROR(219, "获取用户信息失败"), + ILLEGAL_DATA_REQUEST(219, "非法数据请求"), + CLASS_NOT_FOUND(219, "类名不存在"), + ADMIN_ROLE_CAN_NOT_DELETED(219, "无法删除admin角色"), + ROUTER_RANK_NEED_LARGER_THAN_THE_PARENT(219, "设置路由等级需要大于或等于父级的路由等级"), + + // 无权访问 403 + FAIL_NO_ACCESS_DENIED(403, "无权访问"), + FAIL_NO_ACCESS_DENIED_USER_OFFLINE(403, "用户强制下线"), + TOKEN_PARSING_FAILED(403, "token解析失败"), + FAIL_NO_ACCESS_DENIED_USER_LOCKED(403, "该账户已封禁"), + + // 系统错误 500 + UNKNOWN_EXCEPTION(500, "服务异常"), + SERVICE_ERROR(500, "服务异常"), + UPLOAD_ERROR(500, "上传失败"), + FAIL(500, "失败"), + ; + + private final Integer code; + private final String message; + + ResultCodeEnum(Integer code, String message) { + this.code = code; + this.message = message; + } +} \ No newline at end of file diff --git a/spring-security/step-2/src/main/java/com/spring/config/Knife4jConfig.java b/spring-security/step-2/src/main/java/com/spring/config/Knife4jConfig.java new file mode 100644 index 0000000..cfee8e3 --- /dev/null +++ b/spring-security/step-2/src/main/java/com/spring/config/Knife4jConfig.java @@ -0,0 +1,49 @@ +package com.spring.config; + +import io.swagger.v3.oas.models.ExternalDocumentation; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Contact; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.info.License; +import lombok.extern.slf4j.Slf4j; +import org.springdoc.core.models.GroupedOpenApi; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@Slf4j +public class Knife4jConfig { + + @Value("${server.port}") + private String port; + + @Bean + public OpenAPI openAPI() { + String url = "http://localhost:" + port; + + // 作者等信息 + Contact contact = new Contact().name("Bunny").email("1319900154@qq.com").url(url); + // 使用协议 + License license = new License().name("MIT").url("https://mit-license.org"); + // 相关信息 + Info info = new Info().title("Bunny-Admin") + .contact(contact).license(license) + .description("Bunny代码生成器") + .summary("Bunny的代码生成器") + .termsOfService(url) + .version("v1.0.0"); + + return new OpenAPI().info(info).externalDocs(new ExternalDocumentation()); + } + + @Bean + public GroupedOpenApi all() { + return GroupedOpenApi.builder().group("全部请求接口").pathsToMatch("/api/**").build(); + } + + @Bean + public GroupedOpenApi security() { + return GroupedOpenApi.builder().group("security接口").pathsToMatch("/api/security/**").build(); + } +} diff --git a/spring-security/step-2/src/main/java/com/spring/controller/CheckController.java b/spring-security/step-2/src/main/java/com/spring/controller/CheckController.java new file mode 100644 index 0000000..3e4b78b --- /dev/null +++ b/spring-security/step-2/src/main/java/com/spring/controller/CheckController.java @@ -0,0 +1,23 @@ +package com.spring.controller; + +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Tag(name = "检查接口", description = "检查当前用户的权限信息") +@RestController +@RequestMapping("/api/security") +public class CheckController { + + @GetMapping("/current-user") + public Authentication getCurrentUser() { + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + System.out.println("Current user: " + auth.getName()); + System.out.println("Authorities: " + auth.getAuthorities()); + return auth; + } + +} diff --git a/spring-security/step-2/src/main/java/com/spring/controller/LoginController.java b/spring-security/step-2/src/main/java/com/spring/controller/LoginController.java new file mode 100644 index 0000000..ba7483e --- /dev/null +++ b/spring-security/step-2/src/main/java/com/spring/controller/LoginController.java @@ -0,0 +1,18 @@ +package com.spring.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class LoginController { + + @GetMapping("") + public String indexPage() { + return "index"; + } + + @GetMapping("/login-page") + public String showLoginPage() { + return "login"; + } +} \ No newline at end of file diff --git a/spring-security/step-2/src/main/java/com/spring/security/config/SecurityConfiguration.java b/spring-security/step-2/src/main/java/com/spring/security/config/SecurityConfiguration.java new file mode 100644 index 0000000..2279036 --- /dev/null +++ b/spring-security/step-2/src/main/java/com/spring/security/config/SecurityConfiguration.java @@ -0,0 +1,65 @@ +package com.spring.security.config; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; + +@Configuration +public class SecurityConfiguration { + + /** + * 添加内存用户 + * + * @return {@link ConditionalOnMissingBean} + */ + @Bean + @ConditionalOnMissingBean(UserDetailsService.class) + InMemoryUserDetailsManager inMemoryUserDetailsManager(PasswordEncoder passwordEncoder) { + // 使用注入的密码加密器进行密码加密 + String generatedPassword = passwordEncoder.encode("123456"); + + // 创建用户 权限为只读 + UserDetails bunny = User.withUsername("bunny").password(generatedPassword).roles("USER").authorities("read").build(); + + // 管理员可以查看全部 + UserDetails admin = User.withUsername("admin").password(generatedPassword).roles("ADMIN").authorities("all", "read").build(); + + // 返回内存中的用户 + return new InMemoryUserDetailsManager(bunny, admin); + } + + /** + * 配置密码编码器Bean + * + *

Spring Security提供了多种密码编码器实现,推荐使用BCryptPasswordEncoder作为默认选择。

+ * + *

特点:

+ *
    + *
  • BCryptPasswordEncoder - 使用bcrypt强哈希算法,自动加盐,是当前最推荐的密码编码器
  • + *
  • Argon2PasswordEncoder - 使用Argon2算法,抗GPU/ASIC攻击,但需要更多内存
  • + *
  • SCryptPasswordEncoder - 使用scrypt算法,内存密集型,抗硬件攻击
  • + *
  • Pbkdf2PasswordEncoder - 使用PBKDF2算法,较老但广泛支持
  • + *
+ * + *

注意:不推荐使用MD5等弱哈希算法,Spring官方也不推荐自定义弱密码编码器。

+ * + * @return PasswordEncoder 密码编码器实例 + * @see BCryptPasswordEncoder + */ + @Bean + public PasswordEncoder passwordEncoder() { + // 其他编码器示例(根据需求选择一种): + // return new Argon2PasswordEncoder(16, 32, 1, 1 << 14, 2); + // return new SCryptPasswordEncoder(); + // return new Pbkdf2PasswordEncoder("secret", 185000, 256); + + // 实际项目中只需返回一个密码编码器 + return new BCryptPasswordEncoder(); + } +} diff --git a/spring-security/step-2/src/main/java/com/spring/security/config/SecurityWebConfiguration.java b/spring-security/step-2/src/main/java/com/spring/security/config/SecurityWebConfiguration.java new file mode 100644 index 0000000..ec537d2 --- /dev/null +++ b/spring-security/step-2/src/main/java/com/spring/security/config/SecurityWebConfiguration.java @@ -0,0 +1,65 @@ +package com.spring.security.config; + +import com.spring.security.handler.SecurityAccessDeniedHandler; +import com.spring.security.handler.SecurityAuthenticationEntryPoint; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.web.SecurityFilterChain; + +@EnableMethodSecurity +@EnableWebSecurity +@Configuration +public class SecurityWebConfiguration { + + @Bean + SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + String[] permitAllUrls = { + "/", "/doc.html/**", + "/webjars/**", "/images/**", ".well-known/**", "favicon.ico", "/error/**", + "/swagger-ui/**", "/v3/api-docs/**" + }; + + http.authorizeHttpRequests(authorizeRequests -> + // 访问路径为 /api 时需要进行认证 + authorizeRequests + .requestMatchers(permitAllUrls).permitAll() + .requestMatchers("/api/security/**").permitAll() + .requestMatchers(HttpMethod.GET, "/api/anonymous/**").anonymous() + // 会自动变成 ROLE_ADMIN + // .requestMatchers("/api/**").hasRole("ADMIN") + .requestMatchers("/api/**").hasAnyAuthority("all", "read") + ) + .formLogin(loginPage -> loginPage + // 自定义登录页路径 + .loginPage("/login-page") + // 处理登录的URL(默认就是/login) + .loginProcessingUrl("/login") + // 登录成功跳转 + .defaultSuccessUrl("/") + // 登录失败跳转 + .failureUrl("/login-page?error=true") + .permitAll() + ) + // 使用默认的登录 + // .formLogin(Customizer.withDefaults()) + // 禁用表单登录 + // .formLogin(AbstractHttpConfigurer::disable) + .logout(logout -> logout + .logoutSuccessUrl("/login-page?logout=true") + .permitAll() + ) + .csrf(AbstractHttpConfigurer::disable) + .exceptionHandling(configurer -> configurer + .accessDeniedHandler(new SecurityAccessDeniedHandler()) + .authenticationEntryPoint(new SecurityAuthenticationEntryPoint()) + ) + ; + + return http.build(); + } +} \ No newline at end of file diff --git a/spring-security/step-2/src/main/java/com/spring/security/handler/SecurityAccessDeniedHandler.java b/spring-security/step-2/src/main/java/com/spring/security/handler/SecurityAccessDeniedHandler.java new file mode 100644 index 0000000..661e686 --- /dev/null +++ b/spring-security/step-2/src/main/java/com/spring/security/handler/SecurityAccessDeniedHandler.java @@ -0,0 +1,28 @@ +package com.spring.security.handler; + +import com.alibaba.fastjson2.JSON; +import com.spring.bean.vo.result.Result; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.access.AccessDeniedHandler; + +import java.io.IOException; + +@Slf4j +public class SecurityAccessDeniedHandler implements AccessDeniedHandler { + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { + log.error("CustomerAccessDeniedHandler:{}", accessDeniedException.getLocalizedMessage()); + + Result result = Result.error(accessDeniedException.getMessage()); + + Object json = JSON.toJSON(result); + + // 返回响应 + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().println(json); + } +} diff --git a/spring-security/step-2/src/main/java/com/spring/security/handler/SecurityAuthenticationEntryPoint.java b/spring-security/step-2/src/main/java/com/spring/security/handler/SecurityAuthenticationEntryPoint.java new file mode 100644 index 0000000..7e48511 --- /dev/null +++ b/spring-security/step-2/src/main/java/com/spring/security/handler/SecurityAuthenticationEntryPoint.java @@ -0,0 +1,29 @@ +package com.spring.security.handler; + +import com.alibaba.fastjson2.JSON; +import com.spring.bean.vo.result.Result; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; + +import java.io.IOException; + +@Slf4j +public class SecurityAuthenticationEntryPoint implements AuthenticationEntryPoint { + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { + log.error("CustomerAccessDeniedHandler:{}", authException.getLocalizedMessage()); + + Result result = Result.error(authException.getMessage()); + + Object json = JSON.toJSON(result); + + // 返回响应 + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().println(json); + } +} diff --git a/spring-security/step-2/src/main/java/com/spring/security/password/MD5PasswordEncoder.java b/spring-security/step-2/src/main/java/com/spring/security/password/MD5PasswordEncoder.java new file mode 100644 index 0000000..1cab71c --- /dev/null +++ b/spring-security/step-2/src/main/java/com/spring/security/password/MD5PasswordEncoder.java @@ -0,0 +1,52 @@ +package com.spring.security.password; + +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.util.DigestUtils; +import org.springframework.util.StringUtils; + +import java.util.HexFormat; + +/** + *

MD5密码编码器实现

+ * + * 安全警告:此类使用MD5算法进行密码哈希,已不再安全,不推荐用于生产环境。 + * + *

MD5算法因其计算速度快且易受彩虹表攻击而被认为不安全。即使密码哈希本身是单向的, + * 但现代计算能力使得暴力破解和预先计算的彩虹表攻击变得可行。

+ * + *

Spring Security推荐使用BCrypt、PBKDF2、Argon2或Scrypt等自适应单向函数替代MD5。

+ * + * @see PasswordEncoder + * 一般仅用于遗留系统兼容,新系统应使用更安全的密码编码器 + */ +public class MD5PasswordEncoder implements PasswordEncoder { + + @Override + public String encode(CharSequence rawPassword) { + if (rawPassword == null) { + throw new IllegalArgumentException("原始密码不能为null"); + } + + byte[] md5Digest = DigestUtils.md5Digest(rawPassword.toString().getBytes()); + return HexFormat.of().formatHex(md5Digest); + } + + @Override + public boolean matches(CharSequence rawPassword, String encodedPassword) { + if (rawPassword == null) { + throw new IllegalArgumentException("原始密码不能为null"); + } + + if (!StringUtils.hasText(encodedPassword)) { + return false; + } + + return encodedPassword.equalsIgnoreCase(encode(rawPassword)); + } + + @Override + public boolean upgradeEncoding(String encodedPassword) { + // MD5已不安全,始终返回true建议升级到更安全的算法 + return true; + } +} \ No newline at end of file diff --git a/spring-security/step-2/src/main/java/com/spring/security/service/CustomUserDetailsService.java b/spring-security/step-2/src/main/java/com/spring/security/service/CustomUserDetailsService.java new file mode 100644 index 0000000..fb727b3 --- /dev/null +++ b/spring-security/step-2/src/main/java/com/spring/security/service/CustomUserDetailsService.java @@ -0,0 +1,35 @@ +package com.spring.security.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class CustomUserDetailsService implements UserDetailsService { + + private final PasswordEncoder passwordEncoder; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + // 1. 这里应该根据username从数据库或其他存储中查询用户信息 + // 以下是模拟数据,实际应用中应从数据库查询 + + // 2. 如果用户不存在,抛出UsernameNotFoundException + if (!"bunny".equalsIgnoreCase(username)) { + throw new UsernameNotFoundException("User not found: " + username); + } + + // 3. 构建UserDetails对象返回 + return User.builder() + .username(username) // 使用传入的用户名 + .password(passwordEncoder.encode("123456")) // 密码应该已经加密存储,这里仅为示例 + .roles("USER") // 角色会自动添加ROLE_前缀 + .authorities("read", "write") // 添加具体权限 + .build(); + } +} \ No newline at end of file diff --git a/spring-security/step-2/src/main/java/com/spring/service/LoginService.java b/spring-security/step-2/src/main/java/com/spring/service/LoginService.java new file mode 100644 index 0000000..53b86d5 --- /dev/null +++ b/spring-security/step-2/src/main/java/com/spring/service/LoginService.java @@ -0,0 +1,4 @@ +package com.spring.service; + +public interface LoginService { +} diff --git a/spring-security/step-2/src/main/java/com/spring/service/impl/LoginServiceImpl.java b/spring-security/step-2/src/main/java/com/spring/service/impl/LoginServiceImpl.java new file mode 100644 index 0000000..49a9525 --- /dev/null +++ b/spring-security/step-2/src/main/java/com/spring/service/impl/LoginServiceImpl.java @@ -0,0 +1,11 @@ +package com.spring.service.impl; + +import com.spring.service.LoginService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class LoginServiceImpl implements LoginService { + +} diff --git a/spring-security/step-2/src/main/resources/application-dev.yml b/spring-security/step-2/src/main/resources/application-dev.yml new file mode 100644 index 0000000..833b8ce --- /dev/null +++ b/spring-security/step-2/src/main/resources/application-dev.yml @@ -0,0 +1,7 @@ +bunny: + master: + host: rm-bp12z6hlv46vi6g8mro.mysql.rds.aliyuncs.com + port: 3306 + database: bunny_test + username: bunny_test + password: "Test1234" \ No newline at end of file diff --git a/spring-security/step-2/src/main/resources/application.yml b/spring-security/step-2/src/main/resources/application.yml new file mode 100644 index 0000000..ac51e5a --- /dev/null +++ b/spring-security/step-2/src/main/resources/application.yml @@ -0,0 +1,34 @@ +server: + port: 8772 + +spring: + application: + name: spring-security + profiles: + active: dev + + datasource: + type: com.zaxxer.hikari.HikariDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://${bunny.master.host}:${bunny.master.port}/${bunny.master.database}?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true + username: ${bunny.master.username} + password: ${bunny.master.password} + hikari: + maximum-pool-size: 20 + connection-timeout: 30000 + + jackson: + date-format: yyyy-MM-dd HH:mm:ss + +mybatis-plus: + mapper-locations: classpath:/mapper/*.xml + global-config: + db-config: + id-type: auto + logic-delete-value: 1 + logic-not-delete-value: 0 + +logging: + level: + com.spring: debug + root: info diff --git a/spring-security/step-2/src/main/resources/banner.txt b/spring-security/step-2/src/main/resources/banner.txt new file mode 100644 index 0000000..4509c36 --- /dev/null +++ b/spring-security/step-2/src/main/resources/banner.txt @@ -0,0 +1,11 @@ + + ____ ____ _ _ + | __ ) _ _ _ __ _ __ _ _ / ___|| |_ _ _ __| |_ _ + | _ \| | | | '_ \| '_ \| | | | \___ \| __| | | |/ _` | | | | + | |_) | |_| | | | | | | | |_| | ___) | |_| |_| | (_| | |_| | + |____/ \__,_|_| |_|_| |_|\__, | |____/ \__|\__,_|\__,_|\__, | + |___/ |___/ + +Service Name${spring.application.name} +SpringBoot Version: ${spring-boot.version}${spring-boot.formatted-version} +Spring Active:${spring.profiles.active} diff --git a/spring-security/step-2/src/main/resources/logback.xml b/spring-security/step-2/src/main/resources/logback.xml new file mode 100644 index 0000000..02b7abe --- /dev/null +++ b/spring-security/step-2/src/main/resources/logback.xml @@ -0,0 +1,72 @@ + + + logback + + + + + + + + + + + + + + DEBUG + + + + %cyan([%thread %d{yyyy-MM-dd HH:mm:ss}]) %yellow(%-5level) %green(%logger{100}).%boldRed(%method)-%boldMagenta(%line)-%blue(%msg%n) + + ${ENCODING} + + + + + + logs/${APP_NAME}/${datetime}.log + true + + %date{yyyy-MM-dd HH:mm:ss} [%-5level] %thread %file:%line %logger %msg%n + ${ENCODING} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-security/step-2/src/main/resources/static/css/css2.css b/spring-security/step-2/src/main/resources/static/css/css2.css new file mode 100644 index 0000000..1659869 --- /dev/null +++ b/spring-security/step-2/src/main/resources/static/css/css2.css @@ -0,0 +1,108 @@ +/* devanagari */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url(https://fonts.gstatic.com/s/poppins/v23/pxiByp8kv8JHgFVrLDz8Z11lFc-K.woff2) format('woff2'); + unicode-range: U+0900-097F, U+1CD0-1CF9, U+200C-200D, U+20A8, U+20B9, U+20F0, U+25CC, U+A830-A839, U+A8E0-A8FF, U+11B00-11B09; +} +/* latin-ext */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url(https://fonts.gstatic.com/s/poppins/v23/pxiByp8kv8JHgFVrLDz8Z1JlFc-K.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url(https://fonts.gstatic.com/s/poppins/v23/pxiByp8kv8JHgFVrLDz8Z1xlFQ.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* devanagari */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/poppins/v23/pxiEyp8kv8JHgFVrJJbecmNE.woff2) format('woff2'); + unicode-range: U+0900-097F, U+1CD0-1CF9, U+200C-200D, U+20A8, U+20B9, U+20F0, U+25CC, U+A830-A839, U+A8E0-A8FF, U+11B00-11B09; +} +/* latin-ext */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/poppins/v23/pxiEyp8kv8JHgFVrJJnecmNE.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/poppins/v23/pxiEyp8kv8JHgFVrJJfecg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* devanagari */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://fonts.gstatic.com/s/poppins/v23/pxiByp8kv8JHgFVrLEj6Z11lFc-K.woff2) format('woff2'); + unicode-range: U+0900-097F, U+1CD0-1CF9, U+200C-200D, U+20A8, U+20B9, U+20F0, U+25CC, U+A830-A839, U+A8E0-A8FF, U+11B00-11B09; +} +/* latin-ext */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://fonts.gstatic.com/s/poppins/v23/pxiByp8kv8JHgFVrLEj6Z1JlFc-K.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://fonts.gstatic.com/s/poppins/v23/pxiByp8kv8JHgFVrLEj6Z1xlFQ.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* devanagari */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/poppins/v23/pxiByp8kv8JHgFVrLCz7Z11lFc-K.woff2) format('woff2'); + unicode-range: U+0900-097F, U+1CD0-1CF9, U+200C-200D, U+20A8, U+20B9, U+20F0, U+25CC, U+A830-A839, U+A8E0-A8FF, U+11B00-11B09; +} +/* latin-ext */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/poppins/v23/pxiByp8kv8JHgFVrLCz7Z1JlFc-K.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/poppins/v23/pxiByp8kv8JHgFVrLCz7Z1xlFQ.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} diff --git a/spring-security/step-2/src/main/resources/static/error/400.html b/spring-security/step-2/src/main/resources/static/error/400.html new file mode 100644 index 0000000..fc1e212 --- /dev/null +++ b/spring-security/step-2/src/main/resources/static/error/400.html @@ -0,0 +1,69 @@ + + + + + 400 错误 - phpstudy + + + + + + + + + + + + + + + +
+
+

HTTP 400 - Bad Request

+
+
错误说明:因为错误的语法导致服务器无法理解请求信息。
+
原因1:客户端发起的请求不符合服务器对请求的某些限制,或者请求本身存在一定的错误。
+
解决办法:
+
链接中有特殊字符或者链接长度过长导致,请对应修改.
+
原因2:request header 或者 cookie 过大所引起
+
解决办法:
+
crtl+shift+delete 快捷键清除cookie.
+
+
+
+ + \ No newline at end of file diff --git a/spring-security/step-2/src/main/resources/static/error/403.html b/spring-security/step-2/src/main/resources/static/error/403.html new file mode 100644 index 0000000..6c281b0 --- /dev/null +++ b/spring-security/step-2/src/main/resources/static/error/403.html @@ -0,0 +1,69 @@ + + + + + 403 错误 - phpstudy + + + + + + + + + + + + + + + +
+
+

403 - Forbidden 禁止访问: 访问被拒绝

+
+
错误说明:禁止访问,服务器拒绝访问
+
原因1:未找到默认的索引文件
+
解决办法:
+
IIS中【启用默认内容文档】选项中将默认打开文档修改为程序首页文件格式,如:index.html或者index.php
+
原因2:文件夹安全权限导致
+
解决办法:
+
程序文件-右击-属性-安全-Users-修改为读取和执行权限
+
+
+
+ + \ No newline at end of file diff --git a/spring-security/step-2/src/main/resources/static/error/404.html b/spring-security/step-2/src/main/resources/static/error/404.html new file mode 100644 index 0000000..6cc5d1e --- /dev/null +++ b/spring-security/step-2/src/main/resources/static/error/404.html @@ -0,0 +1,78 @@ + + + + + 404 错误 - phpstudy + + + + + + + + + + + + + + + +
+
+

404 - Page Not Found 未找到

+
+
错误说明:请求的页面不存在
+
原因1:访问的文档权限不够
+
解决办法:
+
修改文件权限为755,windos系统修改目录权限为可写可读。
+
原因2:防火墙的原因
+
解决办法:
+
先关闭让防火墙通过WWW服务。
+
原因3:站点根目录无默认访问文件
+
解决办法:
+
在根目录中创建index.html或者创建index.php。
+
原因4:站点配置目录不正确
+
解决办法:
+
将网站应用程序复制到站点目录中,或者修改站点配置目录指定到应用程序目录中。
+
原因5:站点使用了伪静态
+
解决办法:
+
将伪静态规则删除,或者重新编写正确的伪静态规则,或关闭伪静态配置。
+
+
+
+ + \ No newline at end of file diff --git a/spring-security/step-2/src/main/resources/static/error/500.html b/spring-security/step-2/src/main/resources/static/error/500.html new file mode 100644 index 0000000..6071bf4 --- /dev/null +++ b/spring-security/step-2/src/main/resources/static/error/500.html @@ -0,0 +1,64 @@ + + + + + 500 - 服务器错误 + + + + +
+

:'(

+

服务器开小差啦!管理员正在修理中...

+

还请阁下静候站点恢复~

+
+ + \ No newline at end of file diff --git a/spring-security/step-2/src/main/resources/static/error/501.html b/spring-security/step-2/src/main/resources/static/error/501.html new file mode 100644 index 0000000..48ac544 --- /dev/null +++ b/spring-security/step-2/src/main/resources/static/error/501.html @@ -0,0 +1,66 @@ + + + + + 501 错误 - phpstudy + + + + + + + + + + + + + + + +
+
+

HTTP 501 - Not Implemented

+
+
错误说明:服务器没有相应的执行动作来完成当前请求。
+
原因1:Web 服务器不支持实现此请求所需的功能
+
解决办法:
+
可以用来HttpWebRequest指定一个UserAgent来试试的,有时候你可以换电脑来测试一下的。
+
+
+
+ + \ No newline at end of file diff --git a/spring-security/step-2/src/main/resources/static/error/502.html b/spring-security/step-2/src/main/resources/static/error/502.html new file mode 100644 index 0000000..ea44be2 --- /dev/null +++ b/spring-security/step-2/src/main/resources/static/error/502.html @@ -0,0 +1,80 @@ + + + + + 502 错误 - phpstudy + + + + + + + + + + + + + + + +
+
+

HTTP 502 - Bad Gateway 没有响应

+
+
错误说明:坏的网关,http向后端节点请求,没有响应
+
原因1:DNS 缓冲
+
解决办法:
+
在dos窗口运行 ipconfig /flushdns,该命令会刷新DNS缓冲。
+
原因2:浏览器代理
+
解决办法:
+
关掉代理。
+
原因3:dns 被劫持了,即使使用国外的dns,也会被劫持
+
解决办法:
+
+ 去掉VPN服务器的DNS。切换另外的dns。在windows系统中,可以在本地网络连接的属性中,去掉默认的dns,选用国外的dns,比如google的或opendns。 +
+
原因4:php执行超时
+
解决办法:
+
修改/usr/local/php/etc/php.ini 将max_execution_time 改为300。
+
原因5:nginx等待时间超时
+
解决办法:
+
适当增加nginx.conf配置文件中FastCGI的timeout时间。
+
+
+
+ + \ No newline at end of file diff --git a/spring-security/step-2/src/main/resources/static/error/503.html b/spring-security/step-2/src/main/resources/static/error/503.html new file mode 100644 index 0000000..c6fec86 --- /dev/null +++ b/spring-security/step-2/src/main/resources/static/error/503.html @@ -0,0 +1,69 @@ + + + + + 503 错误 - phpstudy + + + + + + + + + + + + + + + +
+
+

HTTP 503 - Service Unavailable 服务不可用

+
+
错误说明:服务当前不可用
+
原因1:服务不可用状态
+
解决办法:
+
服务器或许就是正在维护或者暂停了,你可以联系一下服务器空间商。
+
原因2:程序占用资源太多
+
解决办法:
+
通过设置应用程序池把账户改为NetworkService即可解决。
+
+
+
+ + \ No newline at end of file diff --git a/spring-security/step-2/src/main/resources/static/error/504.html b/spring-security/step-2/src/main/resources/static/error/504.html new file mode 100644 index 0000000..2980dd0 --- /dev/null +++ b/spring-security/step-2/src/main/resources/static/error/504.html @@ -0,0 +1,81 @@ + + + + + 504 错误 - phpstudy + + + + + + + + + + + + + + + +
+
+

HTTP 504 - Gateway Timeout 网关超时

+
+
错误说明:网关超时,服务器响应时间,达到超出设定的范围
+
原因1:后端电脑之间 IP 通讯缓慢而产生
+
解决办法:
+
如果您的 Web 服务器由某一网站托管, 只有负责那个网站设置的人员才能解决这个问题。
+
原因2:由于nginx默认的fastcgi进程响应的缓冲区太小造成的错误
+
解决办法:
+
一般默认的fastcgi进程响应的缓冲区是8K,这时可以设置大一点,在nginx.conf里,加入:fastcgi_buffers 8 + 128k这表示设置fastcgi缓冲区为8块128k大小的空间。当然如果在进行某一项即时的操作, 可能需要nginx的超时参数调大点, + 例如设置成60秒:send_timeout 60;经过这两个参数的调整,一般不会再提示“504 Gateway Time-out”错误,问题基本解决。 +
+
原因3:PHP环境的配置问题
+
解决办法:
+
更改php-fpm的几处配置: 把max_children由之前的10改为现在的30,这样就可以保证有充足的php-cgi进程可以被使用; + 把request_terminate_timeout由之前的0s改为60s,这样php-cgi进程 处理脚本的超时时间就是60秒,可以防止进程都被挂起,提高利用效率。 + 接着再更改nginx的几个配置项,减少FastCGI的请求次数,尽量维持buffers不变: fastcgi_buffers由 4 64k 改为 2 + 256k; fastcgi_buffer_size 由 64k 改为 128K; fastcgi_busy_buffers_size 由 128K 改为 256K; + fastcgi_temp_file_write_size 由 128K 改为 256K。 重新加载php-fpm和nginx的配置,再次测试,如果没有出现“504 + Gateway Time-out”错误,问题解决。 +
+
+
+
+ + \ No newline at end of file diff --git a/spring-security/step-2/src/main/resources/static/error/505.html b/spring-security/step-2/src/main/resources/static/error/505.html new file mode 100644 index 0000000..1cd5dd5 --- /dev/null +++ b/spring-security/step-2/src/main/resources/static/error/505.html @@ -0,0 +1,72 @@ + + + + + 505 错误 - phpstudy + + + + + + + + + + + + + + + +
+
+

HTTP 505 - HTTP Version Not Supported

+
+
错误说明:HTTP 版本不受支持。
+
原因1:您的 Web 服务器不支持,或拒绝支持客户端(如您的浏览器)在发送给服务器的 HTTP 请求数据流中指定的 HTTP + 协议版本 +
+
解决办法:
+
升级您的 Web 服务器软件。
+
原因2:http请求格式的错误
+
解决办法:
+
对照一下自己的代码,从打印的信息中终于找到问题所在。可能在请求后面多加了一个空格。http协议真是很严格了。 +
+
+
+
+ + \ No newline at end of file diff --git a/spring-security/step-2/src/main/resources/static/error/506.html b/spring-security/step-2/src/main/resources/static/error/506.html new file mode 100644 index 0000000..8160abd --- /dev/null +++ b/spring-security/step-2/src/main/resources/static/error/506.html @@ -0,0 +1,66 @@ + + + + + 506 错误 - phpstudy + + + + + + + + + + + + + + + +
+
+

HTTP 506 - Variant Also Negotiates

+
+
错误说明:
+
原因1:服务器存在内部配置错误
+
解决办法:
+
被请求的协商变元资源被配置为在透明内容协商中使用自己,因此在一个协商处理中不是一个合适的重点。
+
+
+
+ + \ No newline at end of file diff --git a/spring-security/step-2/src/main/resources/static/error/507.html b/spring-security/step-2/src/main/resources/static/error/507.html new file mode 100644 index 0000000..fb6c7e7 --- /dev/null +++ b/spring-security/step-2/src/main/resources/static/error/507.html @@ -0,0 +1,66 @@ + + + + + 507 错误 - phpstudy + + + + + + + + + + + + + + + +
+
+

HTTP 507 - Insufficient Storage

+
+
错误说明:
+
原因1:服务器无法存储完成请求所必须的内容
+
解决办法:
+
这个状况被认为是临时的。WebDAV (RFC 4918)。
+
+
+
+ + \ No newline at end of file diff --git a/spring-security/step-2/src/main/resources/static/error/509.html b/spring-security/step-2/src/main/resources/static/error/509.html new file mode 100644 index 0000000..520abbd --- /dev/null +++ b/spring-security/step-2/src/main/resources/static/error/509.html @@ -0,0 +1,66 @@ + + + + + 509 错误 - phpstudy + + + + + + + + + + + + + + + +
+
+

HTTP 509 - Bandwidth Limit Exceeded

+
+
错误说明:
+
原因1:网站流量已经超出您所购买的方案限制即服务器达到带宽限制
+
解决办法:
+
1.升级方案 2.等到下个月后流量重新计算,网站即可正常浏览。
+
+
+
+ + \ No newline at end of file diff --git a/spring-security/step-2/src/main/resources/static/error/510.html b/spring-security/step-2/src/main/resources/static/error/510.html new file mode 100644 index 0000000..95b2f9f --- /dev/null +++ b/spring-security/step-2/src/main/resources/static/error/510.html @@ -0,0 +1,66 @@ + + + + + 510 错误 - phpstudy + + + + + + + + + + + + + + + +
+
+

HTTP 510 - Not Extended

+
+
错误说明:
+
原因1:获取资源所需要的策略并没有被满足
+
解决办法:
+
需要请求有额外的扩展内容,服务器才能处理请求。
+
+
+
+ + \ No newline at end of file diff --git a/spring-security/step-2/src/main/resources/static/favicon.ico b/spring-security/step-2/src/main/resources/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..385f8a67127e1978b08387383f5935feaf561d04 GIT binary patch literal 17014 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 G5Bv)+nYH-< literal 0 HcmV?d00001 diff --git a/spring-security/step-2/src/main/resources/templates/index.html b/spring-security/step-2/src/main/resources/templates/index.html new file mode 100644 index 0000000..15d63fc --- /dev/null +++ b/spring-security/step-2/src/main/resources/templates/index.html @@ -0,0 +1,503 @@ + + + + + + Spring Security 6 学习中心 + + + + + + + + + +
+
+ +
+
+ + +
+
+
+

掌握 Spring Security 6

+

学习最强大的Java安全框架,保护您的应用程序免受现代安全威胁。Spring Security + 6提供了全面的身份验证和授权功能,让您的应用安全无忧。

+ +
+
+
+ + +
+
+
+

Spring Security 6 核心特性

+

Spring Security 6引入了许多强大的新功能,使应用程序安全比以往任何时候都更简单、更强大。

+
+
+
+
+ +
+

现代化的认证

+

支持OAuth 2.0、OpenID Connect、SAML 2.0等多种认证协议,满足现代应用的安全需求。

+
+
+
+ +
+

强大的授权

+

细粒度的权限控制,支持方法级安全、领域对象安全等多种授权模式。

+
+
+
+ +
+

防护机制

+

内置CSRF防护、点击劫持防护、内容安全策略等安全机制,保护应用免受常见攻击。

+
+
+
+
+ + +
+
+
+

学习资源与文档

+

探索我们的文档和工具,快速掌握Spring Security 6的强大功能。

+
+
+
+
+
+

API 文档

+

详细的API参考文档,包含所有类、方法和配置选项的详细说明,帮助您充分利用Spring Security + 6的所有功能。

+ 查看API文档 +
+
+
+
+
+

Swagger UI

+

交互式API文档,可以直接在浏览器中测试API端点,查看请求和响应示例,加快开发流程。

+ 访问Swagger UI +
+
+
+
+
+ + +
+
+ + +
+
+ + \ No newline at end of file diff --git a/spring-security/step-2/src/main/resources/templates/login.html b/spring-security/step-2/src/main/resources/templates/login.html new file mode 100644 index 0000000..247581e --- /dev/null +++ b/spring-security/step-2/src/main/resources/templates/login.html @@ -0,0 +1,206 @@ + + + + + + 登录 | 您的应用名称 + + + + + + + + + + +
+ +
+ + + + \ No newline at end of file