mirror of
				https://github.com/continew-org/continew-admin.git
				synced 2025-10-31 10:57:13 +08:00 
			
		
		
		
	新增:新增用户登录和退出 API(引入 Sa-Token 依赖,详情可见 README 介绍)
This commit is contained in:
		| @@ -33,6 +33,8 @@ import org.springframework.context.annotation.Import; | ||||
| import org.springframework.web.bind.annotation.GetMapping; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
|  | ||||
| import cn.dev33.satoken.annotation.SaIgnore; | ||||
|  | ||||
| import top.charles7c.cnadmin.common.config.properties.ContinewAdminProperties; | ||||
|  | ||||
| /** | ||||
| @@ -62,6 +64,7 @@ public class ContinewAdminApplication implements ApplicationRunner { | ||||
|      * @return / | ||||
|      */ | ||||
|     @Hidden | ||||
|     @SaIgnore | ||||
|     @GetMapping("/") | ||||
|     public String index() { | ||||
|         return String.format("%s backend service started successfully.", properties.getName()); | ||||
|   | ||||
| @@ -30,6 +30,7 @@ import org.springframework.web.bind.annotation.RestController; | ||||
|  | ||||
| import com.wf.captcha.base.Captcha; | ||||
|  | ||||
| import cn.dev33.satoken.annotation.SaIgnore; | ||||
| import cn.hutool.core.util.IdUtil; | ||||
|  | ||||
| import top.charles7c.cnadmin.auth.config.properties.CaptchaProperties; | ||||
| @@ -44,6 +45,7 @@ import top.charles7c.cnadmin.common.util.RedisUtils; | ||||
|  * @since 2022/12/11 14:00 | ||||
|  */ | ||||
| @Tag(name = "验证码 API") | ||||
| @SaIgnore | ||||
| @RestController | ||||
| @RequiredArgsConstructor | ||||
| @RequestMapping(value = "/captcha", produces = MediaType.APPLICATION_JSON_VALUE) | ||||
|   | ||||
| @@ -0,0 +1,88 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
|  | ||||
| package top.charles7c.cnadmin.webapi.controller.auth; | ||||
|  | ||||
| import lombok.RequiredArgsConstructor; | ||||
|  | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.Parameter; | ||||
| import io.swagger.v3.oas.annotations.enums.ParameterIn; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
|  | ||||
| import org.springframework.http.MediaType; | ||||
| import org.springframework.validation.annotation.Validated; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
|  | ||||
| import cn.dev33.satoken.annotation.SaIgnore; | ||||
| import cn.dev33.satoken.stp.StpUtil; | ||||
|  | ||||
| import top.charles7c.cnadmin.auth.config.properties.CaptchaProperties; | ||||
| import top.charles7c.cnadmin.auth.model.request.LoginRequest; | ||||
| import top.charles7c.cnadmin.auth.model.vo.LoginVO; | ||||
| import top.charles7c.cnadmin.auth.service.LoginService; | ||||
| import top.charles7c.cnadmin.common.config.properties.RsaProperties; | ||||
| import top.charles7c.cnadmin.common.model.vo.R; | ||||
| import top.charles7c.cnadmin.common.util.CheckUtils; | ||||
| import top.charles7c.cnadmin.common.util.ExceptionUtils; | ||||
| import top.charles7c.cnadmin.common.util.RedisUtils; | ||||
| import top.charles7c.cnadmin.common.util.SecureUtils; | ||||
|  | ||||
| /** | ||||
|  * 登录 API | ||||
|  * | ||||
|  * @author Charles7c | ||||
|  * @since 2022/12/21 20:37 | ||||
|  */ | ||||
| @Tag(name = "登录 API") | ||||
| @RestController | ||||
| @RequiredArgsConstructor | ||||
| @RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE) | ||||
| public class LoginController { | ||||
|  | ||||
|     private final LoginService loginService; | ||||
|     private final CaptchaProperties captchaProperties; | ||||
|  | ||||
|     @SaIgnore | ||||
|     @Operation(summary = "用户登录", description = "根据用户名和密码进行登录认证") | ||||
|     @PostMapping("/login") | ||||
|     public R<LoginVO> login(@Validated @RequestBody LoginRequest loginRequest) { | ||||
|         // 校验验证码 | ||||
|         String captchaKey = RedisUtils.formatKey(captchaProperties.getKeyPrefix(), loginRequest.getUuid()); | ||||
|         String captcha = RedisUtils.getCacheObject(captchaKey); | ||||
|         CheckUtils.exIfBlank(captcha, "验证码已失效"); | ||||
|         RedisUtils.deleteCacheObject(captchaKey); | ||||
|         CheckUtils.exIfCondition(() -> !captcha.equalsIgnoreCase(loginRequest.getCaptcha()), "验证码错误"); | ||||
|  | ||||
|         // 用户登录 | ||||
|         String rawPassword = ExceptionUtils | ||||
|             .exToNull(() -> SecureUtils.decryptByRsaPrivateKey(loginRequest.getPassword(), RsaProperties.PRIVATE_KEY)); | ||||
|         CheckUtils.exIfBlank(rawPassword, "密码解密失败"); | ||||
|         String token = loginService.login(loginRequest.getUsername(), rawPassword); | ||||
|         return R.ok(new LoginVO().setToken(token)); | ||||
|     } | ||||
|  | ||||
|     @SaIgnore | ||||
|     @Operation(summary = "用户退出", description = "注销用户的当前登录") | ||||
|     @Parameter(name = "Authorization", description = "令牌", required = true, example = "Bearer xxxxxxxxx", | ||||
|         in = ParameterIn.HEADER) | ||||
|     @PostMapping("/logout") | ||||
|     public R logout() { | ||||
|         CheckUtils.exIfCondition(() -> !StpUtil.isLogin(), "Token 无效"); | ||||
|         StpUtil.logout(); | ||||
|         return R.ok(); | ||||
|     } | ||||
| } | ||||
| @@ -19,6 +19,29 @@ spring: | ||||
|     # 是否开启 SSL | ||||
|     ssl: false | ||||
|  | ||||
| --- ### 安全配置 | ||||
| security: | ||||
|   # 排除路径配置 | ||||
|   excludes: | ||||
|     # 静态资源 | ||||
|     - /*.html | ||||
|     - /**/*.html | ||||
|     - /**/*.css | ||||
|     - /**/*.js | ||||
|     - /webSocket/** | ||||
|     # 接口文档相关资源 | ||||
|     - /favicon.ico | ||||
|     - /doc.html | ||||
|     - /webjars/** | ||||
|     - /swagger-ui/** | ||||
|     - /swagger-resources/** | ||||
|     - /*/api-docs/** | ||||
|  | ||||
| --- ### 非对称加密配置(例如:密码加密传输,前端公钥加密,后端私钥解密;在线生成 RSA 密钥对:http://web.chacuo.net/netrsakeypair) | ||||
| rsa: | ||||
|   # 私钥 | ||||
|   privateKey: MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAznV2Bi0zIX61NC3zSx8U6lJXbtru325pRV4Wt0aJXGxy6LMTsfxIye1ip+f2WnxrkYfk/X8YZ6FWNQPaAX/iRwIDAQABAkEAk/VcAusrpIqA5Ac2P5Tj0VX3cOuXmyouaVcXonr7f+6y2YTjLQuAnkcfKKocQI/juIRQBFQIqqW/m1nmz1wGeQIhAO8XaA/KxzOIgU0l/4lm0A2Wne6RokJ9HLs1YpOzIUmVAiEA3Q9DQrpAlIuiT1yWAGSxA9RxcjUM/1kdVLTkv0avXWsCIE0X8woEjK7lOSwzMG6RpEx9YHdopjViOj1zPVH61KTxAiBmv/dlhqkJ4rV46fIXELZur0pj6WC3N7a4brR8a+CLLQIhAMQyerWl2cPNVtE/8tkziHKbwW3ZUiBXU24wFxedT9iV | ||||
|  | ||||
| --- ### 验证码配置 | ||||
| captcha: | ||||
|   # 类型 | ||||
|   | ||||
| @@ -19,6 +19,22 @@ spring: | ||||
|     # 是否开启 SSL | ||||
|     ssl: false | ||||
|  | ||||
| --- ### 安全配置 | ||||
| security: | ||||
|   # 排除路径配置 | ||||
|   excludes: | ||||
|     # 静态资源 | ||||
|     - /*.html | ||||
|     - /**/*.html | ||||
|     - /**/*.css | ||||
|     - /**/*.js | ||||
|     - /webSocket/** | ||||
|  | ||||
| --- ### 非对称加密配置(例如:密码加密传输,前端公钥加密,后端私钥解密;在线生成 RSA 密钥对:http://web.chacuo.net/netrsakeypair) | ||||
| rsa: | ||||
|   # 私钥 | ||||
|   privateKey: MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAznV2Bi0zIX61NC3zSx8U6lJXbtru325pRV4Wt0aJXGxy6LMTsfxIye1ip+f2WnxrkYfk/X8YZ6FWNQPaAX/iRwIDAQABAkEAk/VcAusrpIqA5Ac2P5Tj0VX3cOuXmyouaVcXonr7f+6y2YTjLQuAnkcfKKocQI/juIRQBFQIqqW/m1nmz1wGeQIhAO8XaA/KxzOIgU0l/4lm0A2Wne6RokJ9HLs1YpOzIUmVAiEA3Q9DQrpAlIuiT1yWAGSxA9RxcjUM/1kdVLTkv0avXWsCIE0X8woEjK7lOSwzMG6RpEx9YHdopjViOj1zPVH61KTxAiBmv/dlhqkJ4rV46fIXELZur0pj6WC3N7a4brR8a+CLLQIhAMQyerWl2cPNVtE/8tkziHKbwW3ZUiBXU24wFxedT9iV | ||||
|  | ||||
| --- ### 验证码配置 | ||||
| captcha: | ||||
|   # 类型 | ||||
|   | ||||
| @@ -3,13 +3,13 @@ continew-admin: | ||||
|   # 名称 | ||||
|   name: ContiNew-Admin | ||||
|   # 应用名称 | ||||
|   appName: @project.parent.name@ | ||||
|   appName: continew-admin | ||||
|   # 版本 | ||||
|   version: @project.version@ | ||||
|   version: 0.0.1-SNAPSHOT | ||||
|   # 描述 | ||||
|   description: @project.parent.description@ | ||||
|   description: ContiNew-Admin (incubating) 中后台管理框架,Continue New Admin,持续以最新流行技术栈构建。 | ||||
|   # URL | ||||
|   url: @project.parent.url@ | ||||
|   url: https://github.com/Charles7c/continew-admin | ||||
|   ## 作者信息配置 | ||||
|   author: | ||||
|     name: Charles7c | ||||
| @@ -54,6 +54,31 @@ knife4j: | ||||
|     # 自定义 footer 内容,支持 Markdown 语法 | ||||
|     footer-custom-content: '[Apache-2.0](https://github.com/Charles7c/continew-admin/blob/dev/LICENSE) | Copyright © 2022-present [ContiNew-Admin](https://github.com/Charles7c/continew-admin)' | ||||
|  | ||||
| --- ### Sa-Token 配置 | ||||
| sa-token: | ||||
|   # token名称(同时也是 cookie 名称) | ||||
|   token-name: Authorization | ||||
|   # token前缀(例如填写 Bearer 实际传参 Authorization: Bearer xxxx-xxxx-xxxx-xxxx) | ||||
|   token-prefix: Bearer | ||||
|   # token有效期(单位:秒,默认 30 天,-1 代表永不过期) | ||||
|   timeout: 86400 | ||||
|   # token临时有效期(单位:秒,指定时间内无操作就视为 token 过期) | ||||
|   activity-timeout: 1800 | ||||
|   # 是否打开自动续签(如果此值为 true,框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作) | ||||
|   auto-renew: true | ||||
|   # 是否允许同一账号并发登录(为 true 时允许一起登录,为 false 时新登录挤掉旧登录) | ||||
|   is-concurrent: true | ||||
|   # 在多人登录同一账号时,是否共用一个 token(为 true 时所有登录共用一个 token,为 false 时每次登录新建一个 token) | ||||
|   is-share: false | ||||
|   # 是否尝试从 header 里读取 Token | ||||
|   is-read-header: true | ||||
|   # 是否尝试从 cookie 里读取 Token,此值为 false 后,StpUtil.login(id) 登录时也不会再往前端注入 Cookie,适合前后端分离模式 | ||||
|   is-read-cookie: false | ||||
|   # 是否打印操作日志 | ||||
|   is-log: false | ||||
|   # JWT秘钥 | ||||
|   jwt-secret-key: asdasdasifhueuiwyurfewbfjsdafjk | ||||
|  | ||||
| --- ### 服务器配置 | ||||
| server: | ||||
|   servlet: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user