数据库相关
This commit is contained in:
parent
881c556f6a
commit
e9ac9d5f99
8
pom.xml
8
pom.xml
|
|
@ -17,13 +17,17 @@
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<!-- 指定编译使用的 Java 版本 -->
|
<!-- 指定编译使用的 Java 版本 -->
|
||||||
<maven.compiler.source>11</maven.compiler.source>
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
<maven.compiler.target>11</maven.compiler.target>
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
<!-- 可选:指定编译编码 -->
|
<!-- 可选:指定编译编码 -->
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-dependencies</artifactId>
|
<artifactId>spring-boot-dependencies</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
http.authorizeRequests()
|
http.authorizeRequests()
|
||||||
.antMatchers("/login", "/css/**", "/js/**", "/img/**", "/libs/**", "/captcha", "/toAuth",
|
.antMatchers("/login", "/css/**", "/js/**", "/img/**", "/libs/**", "/captcha", "/toAuth","/redirect",
|
||||||
"/ws", "/swagger-ui.html",
|
"/ws", "/swagger-ui.html",
|
||||||
"/swagger-ui/**",
|
"/swagger-ui/**",
|
||||||
"/v3/api-docs",
|
"/v3/api-docs",
|
||||||
|
|
|
||||||
|
|
@ -1,76 +1,246 @@
|
||||||
package com.hshh.nation.login.controller;
|
package com.hshh.nation.login.controller;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.hshh.nation.advice.GlobalExceptionHandler;
|
||||||
import com.hshh.nation.common.BaseController;
|
import com.hshh.nation.common.BaseController;
|
||||||
import com.hshh.nation.common.OperateResult;
|
import com.hshh.nation.common.OperateResult;
|
||||||
import com.hshh.nation.advice.GlobalExceptionHandler;
|
|
||||||
import com.hshh.nation.login.model.ExtendUserDetails;
|
import com.hshh.nation.login.model.ExtendUserDetails;
|
||||||
import com.hshh.nation.set.service.ConfigService;
|
import com.hshh.nation.set.service.ConfigService;
|
||||||
|
import com.hshh.nation.user.entity.User;
|
||||||
|
import com.hshh.nation.user.service.UserService;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import javax.annotation.Resource;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import java.util.Map;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class LoginController extends BaseController {
|
public class LoginController extends BaseController {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ConfigService configService;//全局配置service
|
private ConfigService configService;//全局配置service
|
||||||
|
private final WebClient webClient = WebClient.create();
|
||||||
|
@Autowired
|
||||||
|
private AuthenticationManager authenticationManager;
|
||||||
|
|
||||||
@Autowired
|
@Value("${third.auth.client_id}")
|
||||||
private AuthenticationManager authenticationManager;
|
private String clientId;
|
||||||
|
@Value("${third.auth.client_secret}")
|
||||||
|
private String clientSecret;
|
||||||
|
|
||||||
//导向到登录页面
|
@Value("${third.auth.token-url}")
|
||||||
@RequestMapping("/login")
|
private String tokenUrl;
|
||||||
public String loginPage(Model model) {
|
@Value("${third.auth.userinfo-url}")
|
||||||
Map<String, String> setMap = configService.getMapAllSet();
|
private String getUserUrl;
|
||||||
String systemTitle = setMap.get("system.title");
|
@Resource
|
||||||
model.addAttribute("systemTitle", systemTitle);
|
private UserService userService;
|
||||||
return "login";
|
@Value("${third.auth.jump_url}")
|
||||||
|
private String jumpUrl;
|
||||||
|
@Value("${third.auth.redirect_url}")
|
||||||
|
private String redirectUrl;
|
||||||
|
@Value("${third.auth.logout_url}")
|
||||||
|
private String logoutUrl;
|
||||||
|
|
||||||
|
//导向到登录页面
|
||||||
|
@RequestMapping("/login")
|
||||||
|
public String loginPage(Model model) {
|
||||||
|
Random random = new Random();
|
||||||
|
|
||||||
|
Map<String, String> setMap = configService.getMapAllSet();
|
||||||
|
|
||||||
|
String url = jumpUrl + "?response_type=code&client_id=" + clientId + "&redirect_uri="
|
||||||
|
+ Base64.getUrlEncoder().encodeToString(redirectUrl.getBytes(StandardCharsets.UTF_8))
|
||||||
|
+ "&active_type=user&state=" + random.nextDouble();
|
||||||
|
log.info("jumpUrl::{}", url);
|
||||||
|
String systemTitle = setMap.get("system.title");
|
||||||
|
model.addAttribute("systemTitle", systemTitle);
|
||||||
|
model.addAttribute("jumpUrl", url);
|
||||||
|
return "login";
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/redirect")
|
||||||
|
|
||||||
|
public String redirect(String code, HttpServletRequest request) {
|
||||||
|
//获取token
|
||||||
|
String token = token(code);
|
||||||
|
LoginForm loginForm = getThirdUserAndSaveUserIfNotExit(token);
|
||||||
|
log.info("loginForm::{}", JSON.toJSONString(loginForm));
|
||||||
|
if (loginForm != null) {
|
||||||
|
authLoginForm(loginForm, request);
|
||||||
}
|
}
|
||||||
|
request.getSession().setAttribute("token", token);
|
||||||
|
return "redirect:/home";
|
||||||
|
}
|
||||||
|
|
||||||
//登录
|
@GetMapping("/out")
|
||||||
@PostMapping("/toAuth")
|
public String logout(HttpServletRequest request) {
|
||||||
@ResponseBody
|
log.info("logout.....");
|
||||||
public OperateResult<String> login(@RequestBody LoginForm loginForm, HttpServletRequest request) {
|
String token = request.getSession().getAttribute("token") == null ? ""
|
||||||
try {
|
: request.getSession().getAttribute("token").toString();
|
||||||
log.info("username={}", loginForm.getUsername());
|
if (StringUtils.isNotBlank(token)) {
|
||||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(loginForm.getUsername(), loginForm.getPassword());
|
//回收token
|
||||||
authenticationManager.authenticate(token);
|
String url =
|
||||||
Authentication authentication = authenticationManager.authenticate(token);
|
logoutUrl + "?client_id=" + clientId + "&client_secret=" + clientSecret + "&access_token="
|
||||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
+ token;
|
||||||
request.getSession().setAttribute("user", authentication.getPrincipal());
|
|
||||||
request.getSession(true).setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error(e.getMessage());
|
|
||||||
return OperateResult.error(null, e.getMessage(), GlobalExceptionHandler.SERVER_ERROR_CODE);
|
|
||||||
|
|
||||||
|
String result = webClient.get()
|
||||||
|
.uri(url)
|
||||||
|
.retrieve()
|
||||||
|
.bodyToMono(String.class)
|
||||||
|
.block();
|
||||||
|
log.info("result::{}", result);
|
||||||
|
if (result != null) {
|
||||||
|
JSONObject jsonObject = JSON.parseObject(result);
|
||||||
|
if (jsonObject.containsKey("code")) {
|
||||||
|
if (jsonObject.getInteger("code") == 200) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return OperateResult.success();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/home")
|
request.getSession().removeAttribute("token");
|
||||||
public String home(Model model) {
|
request.getSession().invalidate();
|
||||||
log.info("home");
|
return "redirect:/login";
|
||||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
}
|
||||||
ExtendUserDetails user = (ExtendUserDetails) authentication.getPrincipal();
|
|
||||||
model.addAttribute("currentUser", user);
|
//登录
|
||||||
return "fragments/layout";
|
@PostMapping("/toAuth")
|
||||||
|
@ResponseBody
|
||||||
|
public OperateResult<String> login(@RequestBody LoginForm loginForm, HttpServletRequest request) {
|
||||||
|
try {
|
||||||
|
log.info("username={}", loginForm.getUsername());
|
||||||
|
authLoginForm(loginForm, request);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return OperateResult.error(null, e.getMessage(), GlobalExceptionHandler.SERVER_ERROR_CODE);
|
||||||
|
|
||||||
}
|
}
|
||||||
@Data
|
return OperateResult.success();
|
||||||
private static class LoginForm{
|
}
|
||||||
String username;
|
|
||||||
String password;
|
private void authLoginForm(LoginForm loginForm, HttpServletRequest request) {
|
||||||
|
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
|
||||||
|
loginForm.getUsername(), loginForm.getPassword());
|
||||||
|
authenticationManager.authenticate(token);
|
||||||
|
Authentication authentication = authenticationManager.authenticate(token);
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||||
|
request.getSession().setAttribute("user", authentication.getPrincipal());
|
||||||
|
request.getSession(true)
|
||||||
|
.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,
|
||||||
|
SecurityContextHolder.getContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/home")
|
||||||
|
public String home(Model model) {
|
||||||
|
log.info("home");
|
||||||
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
ExtendUserDetails user = (ExtendUserDetails) authentication.getPrincipal();
|
||||||
|
model.addAttribute("currentUser", user);
|
||||||
|
return "fragments/layout";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class LoginForm {
|
||||||
|
|
||||||
|
String username;
|
||||||
|
String password;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String token(String code) {
|
||||||
|
try {
|
||||||
|
String url = tokenUrl + "?client_id=" + clientId + "&client_secret=" + clientSecret
|
||||||
|
+ "&grant_type=authorization_code&code=" + code;
|
||||||
|
log.info("tokenUrl: {}", url);
|
||||||
|
String result = webClient.get()
|
||||||
|
.uri(url)
|
||||||
|
.retrieve()
|
||||||
|
.bodyToMono(String.class)
|
||||||
|
.block();
|
||||||
|
log.info("token: {}", result);
|
||||||
|
JSONObject resultObject = JSON.parseObject(result);
|
||||||
|
if (resultObject != null && resultObject.containsKey("code")) {
|
||||||
|
if (resultObject.getInteger("code") == 200) {
|
||||||
|
return resultObject.getJSONObject("data").getString("access_token");
|
||||||
|
}
|
||||||
|
return resultObject.getString("access_token");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginForm getThirdUserAndSaveUserIfNotExit(String token) {
|
||||||
|
String userUrl = getUserUrl + "?access_token=" + token;
|
||||||
|
log.info("getUserUrl: {}", userUrl);
|
||||||
|
try {
|
||||||
|
String result = webClient.get()
|
||||||
|
.uri(userUrl)
|
||||||
|
.retrieve()
|
||||||
|
.bodyToMono(String.class)
|
||||||
|
.block();
|
||||||
|
log.info("getUserUrl result: {}", result);
|
||||||
|
JSONObject resultObject = JSON.parseObject(result);
|
||||||
|
if (resultObject != null && resultObject.containsKey("code")) {
|
||||||
|
if (resultObject.getInteger("code") == 200) {
|
||||||
|
|
||||||
|
User user = getUser(resultObject.getJSONObject("data"));
|
||||||
|
User userInDb = userService.getUserByUserId(user.getUserId());
|
||||||
|
if (userInDb == null) {
|
||||||
|
//插入到数据库
|
||||||
|
User newUser = new User();
|
||||||
|
newUser.setUserId(user.getUserId());
|
||||||
|
newUser.setUserName(user.getUserName());
|
||||||
|
newUser.setPassword(new BCryptPasswordEncoder().encode(user.getPassword()));
|
||||||
|
newUser.setNickName(user.getNickName());
|
||||||
|
newUser.setSuperFlag(1);
|
||||||
|
userService.save(newUser);
|
||||||
|
}
|
||||||
|
LoginForm loginForm = new LoginForm();
|
||||||
|
loginForm.setUsername(user.getUserName());
|
||||||
|
loginForm.setPassword(user.getPassword());
|
||||||
|
return loginForm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private User getUser(JSONObject userObject) {
|
||||||
|
User user = new User();
|
||||||
|
user.setUserId(userObject.getString("userId"));
|
||||||
|
user.setUserName(userObject.getString("userName"));
|
||||||
|
user.setNickName(userObject.getString("nickName"));
|
||||||
|
|
||||||
|
user.setPassword(userObject.getString("password"));
|
||||||
|
|
||||||
|
return user;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.hshh.nation.login.model;
|
package com.hshh.nation.login.model;
|
||||||
|
|
||||||
import com.hshh.nation.menu.entity.Menu;
|
import com.hshh.nation.menu.entity.Menu;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
@ -37,7 +38,7 @@ public class ExtendUserDetails implements UserDetails {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||||
return List.of();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.hshh.nation.user.entity;
|
package com.hshh.nation.user.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
@ -43,4 +44,6 @@ public class User implements Serializable {
|
||||||
* 超级管理员标志.
|
* 超级管理员标志.
|
||||||
*/
|
*/
|
||||||
private int superFlag;
|
private int superFlag;
|
||||||
|
private String userId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,4 +19,5 @@ public interface UserService extends IService<User> {
|
||||||
* @return 用户对象.
|
* @return 用户对象.
|
||||||
*/
|
*/
|
||||||
User getUserByUsername(String username);
|
User getUserByUsername(String username);
|
||||||
|
User getUserByUserId(String userId);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,4 +28,15 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User getUserByUserId(String userId) {
|
||||||
|
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
|
||||||
|
queryWrapper.eq("user_id", userId);
|
||||||
|
List<User> list = this.list(queryWrapper);
|
||||||
|
if (!list.isEmpty()) {
|
||||||
|
return list.get(0);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,14 +17,14 @@ spring:
|
||||||
max-wait: -1ms
|
max-wait: -1ms
|
||||||
datasource:
|
datasource:
|
||||||
# mysql
|
# mysql
|
||||||
# url: jdbc:mysql://localhost:3306/nation_defence?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC
|
url: jdbc:mysql://localhost:3306/nation_defence?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC
|
||||||
# username: root
|
username: root
|
||||||
# password: 123456
|
password: 123456
|
||||||
# driver-class-name: com.mysql.cj.jdbc.Driver
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
url: jdbc:dm://192.168.0.52:5236
|
# url: jdbc:dm://127.0.0.1:5236
|
||||||
username: NATION_DEFENCE
|
# username: SYSDBA
|
||||||
password: Lidy1234
|
# password: SYSDBA001
|
||||||
driver-class-name: dm.jdbc.driver.DmDriver
|
# driver-class-name: dm.jdbc.driver.DmDriver
|
||||||
hikari:
|
hikari:
|
||||||
minimum-idle: 5
|
minimum-idle: 5
|
||||||
maximum-pool-size: 20
|
maximum-pool-size: 20
|
||||||
|
|
@ -63,4 +63,13 @@ logging:
|
||||||
level:
|
level:
|
||||||
com.baomidou.mybatisplus: warn
|
com.baomidou.mybatisplus: warn
|
||||||
org.apache.ibatis: warn
|
org.apache.ibatis: warn
|
||||||
|
third:
|
||||||
|
auth:
|
||||||
|
client_id: 233
|
||||||
|
client_secret: 123
|
||||||
|
token-url: http://32.15.80.150:99/oauth2Server/oauth2/token
|
||||||
|
userinfo-url: http://32.15.80.150:99/oauth2Server/oauth2/userinfo
|
||||||
|
jump_url: http://32.15.80.150:99/oauth2Server/oauth2/authorizeV2
|
||||||
|
redirect_url: http://32.15.191.88:8888/redirect
|
||||||
|
logout_url: ttp://32.15.80.150:99/oauth2Server/oauth2/logout
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<div class="dropdown-menu dropdown-menu-end dropdown-menu-arrow">
|
<div class="dropdown-menu dropdown-menu-end dropdown-menu-arrow">
|
||||||
<a th:href="@{/logout}" class="dropdown-item">退出登录</a>
|
<a th:href="@{/out}" class="dropdown-item">退出登录</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -2,160 +2,172 @@
|
||||||
|
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"/>
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
|
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
|
||||||
<title>登录</title>
|
<title>登录</title>
|
||||||
<!-- CSS files -->
|
<!-- CSS files -->
|
||||||
<link th:href="@{/css/tabler.min.css?1684106062}" rel="stylesheet"/>
|
<link th:href="@{/css/tabler.min.css?1684106062}" rel="stylesheet"/>
|
||||||
<link th:href="@{/css/tabler-flags.min.css?1684106062}" rel="stylesheet"/>
|
<link th:href="@{/css/tabler-flags.min.css?1684106062}" rel="stylesheet"/>
|
||||||
<link th:href="@{/css/tabler-payments.min.css?1684106062}" rel="stylesheet"/>
|
<link th:href="@{/css/tabler-payments.min.css?1684106062}" rel="stylesheet"/>
|
||||||
<link th:href="@{/css/tabler-vendors.min.css?1684106062}" rel="stylesheet"/>
|
<link th:href="@{/css/tabler-vendors.min.css?1684106062}" rel="stylesheet"/>
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--tblr-font-sans-serif: 'Inter Var', -apple-system, BlinkMacSystemFont, San Francisco, Segoe UI, Roboto, Helvetica Neue, sans-serif;
|
--tblr-font-sans-serif: 'Inter Var', -apple-system, BlinkMacSystemFont, San Francisco, Segoe UI, Roboto, Helvetica Neue, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-feature-settings: "cv03", "cv04", "cv11";
|
font-feature-settings: "cv03", "cv04", "cv11";
|
||||||
}
|
}
|
||||||
|
|
||||||
.captcha-img {
|
.captcha-img {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* style.css */
|
/* style.css */
|
||||||
.error-message {
|
.error-message {
|
||||||
/* 设置背景与边框,让错误信息更醒目 */
|
/* 设置背景与边框,让错误信息更醒目 */
|
||||||
background-color: #f8d7da;
|
background-color: #f8d7da;
|
||||||
border: 1px solid #f5c6cb;
|
border: 1px solid #f5c6cb;
|
||||||
color: #721c24;
|
color: #721c24;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
|
||||||
/* 居中显示 */
|
/* 居中显示 */
|
||||||
text-align: center; /* 内部文本水平居中 */
|
text-align: center; /* 内部文本水平居中 */
|
||||||
margin: 20px auto; /* 外边距自动左右居中 */
|
margin: 20px auto; /* 外边距自动左右居中 */
|
||||||
|
|
||||||
/* 宽度可以根据需要设置,也可以不设置 */
|
/* 宽度可以根据需要设置,也可以不设置 */
|
||||||
width: 80%; /* 设置一个宽度 */
|
width: 80%; /* 设置一个宽度 */
|
||||||
max-width: 400px; /* 最大宽度 */
|
max-width: 400px; /* 最大宽度 */
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class=" d-flex flex-column">
|
<body class=" d-flex flex-column">
|
||||||
|
|
||||||
|
|
||||||
<div class="page page-center">
|
<div class="page page-center">
|
||||||
<div class="container container-tight py-4">
|
<div class="container container-tight py-4">
|
||||||
|
|
||||||
<div class="card card-md">
|
|
||||||
<div class="card-body">
|
|
||||||
<h2 class="h2 text-center mb-4" th:text="${systemTitle}"></h2>
|
|
||||||
<form name="loginForm" id="loginForm" th:action="@{/toAuth}" method="get" autocomplete="off" novalidate>
|
|
||||||
<div class="mb-3">
|
|
||||||
|
|
||||||
<input type="text" id="username" name="username" class="form-control " placeholder="用户名"
|
|
||||||
autocomplete="off">
|
|
||||||
<div class="invalid-feedback" id="userName_error_tip"></div>
|
|
||||||
</div>
|
|
||||||
<div class="mb-2">
|
|
||||||
<div class="input-group input-group-flat">
|
|
||||||
<input type="password" id="password" name="password" class="form-control "
|
|
||||||
placeholder="密码" autocomplete="off">
|
|
||||||
<div class="invalid-feedback" id="password_error_tip"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-footer">
|
|
||||||
<button type="submit" class="btn btn-primary w-100">登录</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
<div class="card card-md">
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="h2 text-center mb-4" th:text="${systemTitle}"></h2>
|
||||||
|
<form name="loginForm" id="loginForm" th:action="@{/toAuth}" method="get" autocomplete="off"
|
||||||
|
novalidate>
|
||||||
|
<div class="mb-3">
|
||||||
|
|
||||||
|
<input type="text" id="username" name="username" class="form-control "
|
||||||
|
placeholder="用户名"
|
||||||
|
autocomplete="off">
|
||||||
|
<div class="invalid-feedback" id="userName_error_tip"></div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-2">
|
||||||
|
<div class="input-group input-group-flat">
|
||||||
|
<input type="password" id="password" name="password" class="form-control "
|
||||||
|
placeholder="密码" autocomplete="off">
|
||||||
|
<div class="invalid-feedback" id="password_error_tip"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="error-message" id="error_message" style="display:none;">
|
</div>
|
||||||
|
|
||||||
</div>
|
<div class="form-footer">
|
||||||
|
<button type="submit" class="btn btn-primary w-100">登录</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-footer">
|
||||||
|
<button type="button" class="btn btn-success w-100" th:data-redirect-url="${jumpUrl}"
|
||||||
|
onclick="jump(this)">统一认证登录
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="error-message" id="error_message" style="display:none;">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- Libs JS -->
|
<!-- Libs JS -->
|
||||||
<!-- Tabler Core -->
|
<!-- Tabler Core -->
|
||||||
<script th:src="@{/js/tabler.min.js}" defer></script>
|
<script th:src="@{/js/tabler.min.js}" defer></script>
|
||||||
<script th:src="@{/js/common/common.js}" ></script>
|
<script th:src="@{/js/common/common.js}"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
<script>
|
<script>
|
||||||
document.getElementById('loginForm').addEventListener("submit", function (e) {
|
function jump(obj) {
|
||||||
// 阻止默认表单提交
|
|
||||||
e.preventDefault();
|
|
||||||
//删除验证
|
|
||||||
removeValidCss("loginForm")
|
|
||||||
// 使用 FormData 获取表单数据
|
|
||||||
var formData = new FormData(this);
|
|
||||||
var object = {};
|
|
||||||
formData.forEach((value, key) => {
|
|
||||||
object[key] = value;
|
|
||||||
});
|
|
||||||
var jsonData = JSON.stringify(object);
|
|
||||||
console.log("转换得到的 JSON 数据:", jsonData);
|
|
||||||
|
|
||||||
// 从 form 的 action 属性获取 URL(Thymeleaf 渲染后会转换为实际地址)
|
;
|
||||||
var formAction = this.getAttribute('action');
|
window.location = obj.dataset.redirectUrl;
|
||||||
|
}
|
||||||
|
|
||||||
// 通过 fetch 发送 AJAX POST 请求,Content-Type 为 application/json
|
document.getElementById('loginForm').addEventListener("submit", function (e) {
|
||||||
fetch(formAction, {
|
// 阻止默认表单提交
|
||||||
method: "POST",
|
e.preventDefault();
|
||||||
headers: {
|
//删除验证
|
||||||
"Content-Type": "application/json"
|
removeValidCss("loginForm")
|
||||||
},
|
// 使用 FormData 获取表单数据
|
||||||
body: jsonData
|
var formData = new FormData(this);
|
||||||
})
|
var object = {};
|
||||||
.then(response => {
|
formData.forEach((value, key) => {
|
||||||
if (!response.ok) {
|
object[key] = value;
|
||||||
throw new Error("网络响应异常");
|
|
||||||
}
|
|
||||||
return response.json();
|
|
||||||
})
|
|
||||||
.then(data => {
|
|
||||||
|
|
||||||
// 根据服务器返回的数据进行处理,比如跳转或显示提示信息
|
|
||||||
if (data.code === 0) {
|
|
||||||
// 例如:跳转到首页
|
|
||||||
|
|
||||||
window.location.href = "/home";
|
|
||||||
} else {
|
|
||||||
if (data.code === -1) {//验证错误
|
|
||||||
//遍历错误信息
|
|
||||||
for (const item of data.errors) {
|
|
||||||
|
|
||||||
|
|
||||||
document.getElementById(item.elementId).classList.add("is-invalid");
|
|
||||||
document.getElementById(item.elementId + "_error_tip").innerHTML = item.message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(data.code===500){//提交错误
|
|
||||||
document.getElementById("error_message").innerHTML = data.message;
|
|
||||||
document.getElementById("error_message").style.display = "block";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error("请求出错:", error);
|
|
||||||
// 你可以在这里显示错误提示信息
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
var jsonData = JSON.stringify(object);
|
||||||
|
console.log("转换得到的 JSON 数据:", jsonData);
|
||||||
|
|
||||||
|
// 从 form 的 action 属性获取 URL(Thymeleaf 渲染后会转换为实际地址)
|
||||||
|
var formAction = this.getAttribute('action');
|
||||||
|
|
||||||
|
// 通过 fetch 发送 AJAX POST 请求,Content-Type 为 application/json
|
||||||
|
fetch(formAction, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
},
|
||||||
|
body: jsonData
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("网络响应异常");
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
|
||||||
|
// 根据服务器返回的数据进行处理,比如跳转或显示提示信息
|
||||||
|
if (data.code === 0) {
|
||||||
|
// 例如:跳转到首页
|
||||||
|
|
||||||
|
window.location.href = "home";
|
||||||
|
} else {
|
||||||
|
if (data.code === -1) {//验证错误
|
||||||
|
//遍历错误信息
|
||||||
|
for (const item of data.errors) {
|
||||||
|
|
||||||
|
document.getElementById(item.elementId).classList.add("is-invalid");
|
||||||
|
document.getElementById(item.elementId + "_error_tip").innerHTML = item.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data.code === 500) {//提交错误
|
||||||
|
document.getElementById("error_message").innerHTML = data.message;
|
||||||
|
document.getElementById("error_message").style.display = "block";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error("请求出错:", error);
|
||||||
|
// 你可以在这里显示错误提示信息
|
||||||
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
Loading…
Reference in New Issue
Block a user