初步配置安全模块,并处理管理操作
This commit is contained in:
parent
a1817ac53f
commit
92a4a07e09
21
pom.xml
21
pom.xml
|
@ -64,9 +64,28 @@
|
|||
<!-- Shiro -->
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-spring</artifactId>
|
||||
<artifactId>shiro-spring-boot-starter</artifactId>
|
||||
<version>1.9.1</version>
|
||||
</dependency>
|
||||
<!-- Jwt Token -->
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-api</artifactId>
|
||||
<version>0.11.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-impl</artifactId>
|
||||
<version>0.11.3</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-jackson</artifactId>
|
||||
<version>0.11.3</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- SpringBoot Test -->
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
|
|
23
src/main/java/com/jsl/oa/config/JwtToken.java
Normal file
23
src/main/java/com/jsl/oa/config/JwtToken.java
Normal file
|
@ -0,0 +1,23 @@
|
|||
package com.jsl.oa.config;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public class JwtToken implements AuthenticationToken {
|
||||
|
||||
private final String token;
|
||||
private final String username;
|
||||
|
||||
@Override
|
||||
public Object getPrincipal() {
|
||||
return token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCredentials() {
|
||||
return token;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package com.jsl.oa.config;
|
||||
|
||||
import com.jsl.oa.services.AccountService;
|
||||
import com.jsl.oa.model.doData.UserDO;
|
||||
import com.jsl.oa.services.UserService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.shiro.authc.*;
|
||||
import org.apache.shiro.authz.AuthorizationInfo;
|
||||
|
@ -10,7 +11,7 @@ import org.apache.shiro.subject.PrincipalCollection;
|
|||
@RequiredArgsConstructor
|
||||
public class MyRealm extends AuthorizingRealm {
|
||||
|
||||
private final AccountService accountService;
|
||||
private final UserService userService;
|
||||
|
||||
/**
|
||||
* 授权
|
||||
|
@ -30,11 +31,21 @@ public class MyRealm extends AuthorizingRealm {
|
|||
*/
|
||||
@Override
|
||||
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
|
||||
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
|
||||
Account account = accountService.findByUsername(token.getUsername());
|
||||
if(account != null){
|
||||
return new SimpleAuthenticationInfo(account,account.getPassword(),getName());
|
||||
JwtToken jwtToken = (JwtToken) authenticationToken;
|
||||
String username = jwtToken.getUsername();
|
||||
|
||||
// 从数据库获取用户信息
|
||||
UserDO userDO = userService.getUserInfoByUsername(username);
|
||||
if (userDO == null) {
|
||||
throw new UnknownAccountException("用户不存在");
|
||||
} else if (!userDO.getAccountNoLocked()) {
|
||||
throw new LockedAccountException("用户已被锁定");
|
||||
} else if (!userDO.getEnabled()) {
|
||||
throw new DisabledAccountException("用户已被禁用");
|
||||
} else if (!userDO.getAccountNoExpired()) {
|
||||
throw new ExpiredCredentialsException("用户已过期");
|
||||
}
|
||||
return null;
|
||||
|
||||
return new SimpleAuthenticationInfo(username, jwtToken.getCredentials(), getName());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,44 +1,46 @@
|
|||
package com.jsl.oa.config;
|
||||
|
||||
import com.jsl.oa.services.UserService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
|
||||
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Configuration
|
||||
@RequiredArgsConstructor
|
||||
public class ShiroConfiguration {
|
||||
|
||||
@Bean
|
||||
public ShiroFilterFactoryBean filterFactoryBean(@Qualifier("manager") DefaultWebSecurityManager manager){
|
||||
// ShiroFilterFactoryBean 用来配置拦截规则
|
||||
ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
|
||||
factoryBean.setSecurityManager(manager);
|
||||
// 设置拦截规则
|
||||
Map<String,String> map = new HashMap<>();
|
||||
map.put("/main","authc");
|
||||
map.put("/manage","perms[manage]");
|
||||
map.put("/administrator","roles[administrator]");
|
||||
factoryBean.setFilterChainDefinitionMap(map);
|
||||
//未授权页面
|
||||
factoryBean.setUnauthorizedUrl("/unauth");
|
||||
return factoryBean;
|
||||
}
|
||||
|
||||
|
||||
private final UserService userService;
|
||||
|
||||
@Bean
|
||||
public DefaultWebSecurityManager manager(@Qualifier("myRealm") MyRealm myRealm){
|
||||
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
|
||||
manager.setRealm(myRealm);
|
||||
return manager;
|
||||
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
|
||||
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
|
||||
shiroFilterFactoryBean.setSecurityManager(securityManager);
|
||||
|
||||
// 配置过滤器规则
|
||||
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
|
||||
filterChainDefinitionMap.put("/auth/**", "anon"); // 登录接口允许匿名访问
|
||||
|
||||
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
|
||||
|
||||
// 设置登录接口
|
||||
shiroFilterFactoryBean.setLoginUrl("/unauthorized");
|
||||
return shiroFilterFactoryBean;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MyRealm myRealm(){
|
||||
return new MyRealm();
|
||||
public DefaultWebSecurityManager securityManager(MyRealm realm) {
|
||||
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
|
||||
securityManager.setRealm(realm);
|
||||
return securityManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MyRealm myRealm() {
|
||||
return new MyRealm(userService);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,26 +10,40 @@ import com.jsl.oa.utils.ResultUtil;
|
|||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.text.ParseException;
|
||||
|
||||
/**
|
||||
* <h1>用户认证控制器</h1>
|
||||
* <hr/>
|
||||
* 用户认证控制器,包含用户注册、用户登录、用户登出接口
|
||||
*
|
||||
* @since v1.0.0
|
||||
* @version v1.1.0
|
||||
* @see AuthService
|
||||
* @see UserRegisterVO
|
||||
* @see UserLoginVO
|
||||
* @see BaseResponse
|
||||
* @see ErrorCode
|
||||
* @see Processing
|
||||
* @see ResultUtil
|
||||
*/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
public class AuthController {
|
||||
private final AuthService authService;
|
||||
|
||||
/**
|
||||
* <h1>用户注册</h1>
|
||||
* <h2>用户注册</h2>
|
||||
* <hr/>
|
||||
* 用户注册接口
|
||||
*
|
||||
* @since v1.0.0
|
||||
* @return {@link BaseResponse}
|
||||
* @author 筱锋xiao_lfeng
|
||||
*/
|
||||
@PostMapping("/user/register")
|
||||
@PostMapping("/auth/register")
|
||||
public BaseResponse authRegister(@RequestBody @Validated UserRegisterVO userRegisterVO, BindingResult bindingResult) throws ParseException {
|
||||
// 判断是否有参数错误
|
||||
if (bindingResult.hasErrors()) {
|
||||
|
@ -39,7 +53,7 @@ public class AuthController {
|
|||
}
|
||||
|
||||
/**
|
||||
* <h1>用户登录</h1>
|
||||
* <h2>用户登录</h2>
|
||||
* <hr/>
|
||||
* 用户登录接口
|
||||
*
|
||||
|
@ -48,7 +62,7 @@ public class AuthController {
|
|||
* @return {@link BaseResponse}
|
||||
* @author 176yunxuan
|
||||
*/
|
||||
@PostMapping("/user/login")
|
||||
@GetMapping("/auth/login")
|
||||
public BaseResponse authLogin(@RequestBody @Validated UserLoginVO userLoginVO, BindingResult bindingResult){
|
||||
// 判断是否有参数错误
|
||||
if (bindingResult.hasErrors()) {
|
||||
|
@ -56,4 +70,8 @@ public class AuthController {
|
|||
}
|
||||
return authService.authLogin(userLoginVO);
|
||||
}
|
||||
|
||||
public BaseResponse authLogout() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,4 +19,9 @@ public class CustomController implements ErrorController {
|
|||
public ResponseEntity<BaseResponse> handleError() {
|
||||
return ResultUtil.error("PageNotFound", 404, "请求资源不存在");
|
||||
}
|
||||
|
||||
@RequestMapping("/unauthorized")
|
||||
public ResponseEntity<BaseResponse> handleUnauthorized() {
|
||||
return ResultUtil.error("Unauthorized", 401, "未授权");
|
||||
}
|
||||
}
|
||||
|
|
24
src/main/java/com/jsl/oa/dao/UserDAO.java
Normal file
24
src/main/java/com/jsl/oa/dao/UserDAO.java
Normal file
|
@ -0,0 +1,24 @@
|
|||
package com.jsl.oa.dao;
|
||||
|
||||
import com.jsl.oa.mapper.UserMapper;
|
||||
import com.jsl.oa.model.doData.UserDO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class UserDAO {
|
||||
|
||||
private final UserMapper userMapper;
|
||||
|
||||
public UserDO getUserInfoByUsername(String username) {
|
||||
UserDO userDO = null;
|
||||
// 从 Redis 获取数据
|
||||
// TODO: 10000-Redis: 从 Redis 获取数据
|
||||
// 从数据库获取用户信息
|
||||
if (userDO == null) {
|
||||
userDO = userMapper.getUserInfoByUsername(username);
|
||||
}
|
||||
return userDO;
|
||||
}
|
||||
}
|
|
@ -10,19 +10,19 @@ import org.apache.ibatis.annotations.Select;
|
|||
public interface UserMapper {
|
||||
|
||||
@Select("SELECT * FROM organize_oa.oa_user WHERE username = #{username}")
|
||||
UserDO getUserByUsername(String username);
|
||||
UserDO getUserInfoByUsername(String username);
|
||||
|
||||
@Select("SELECT * FROM organize_oa.oa_user WHERE user_num = #{userNum}")
|
||||
UserDO getUserByUserNum(String userNum);
|
||||
@Select("SELECT * FROM organize_oa.oa_user WHERE job_id = #{jobId}")
|
||||
UserDO getUserByUserNum(String jobId);
|
||||
|
||||
@Insert("INSERT INTO organize_oa.oa_user (user_num, username, password, sex, age, unit, field, hometown, kind, state) " +
|
||||
"VALUES " +
|
||||
"(#{userNum}, #{username}, #{password}, #{sex}, #{age}, #{unit}, #{filed}, #{hometown}, #{kind}, #{state})")
|
||||
Boolean insertUser(UserDO userDO);
|
||||
@Insert("INSERT INTO organize_oa.oa_user " +
|
||||
"(job_id, username, password, address, phone, email, age, signature, avatar, nickname, account_no_locked, description, updated_at) " +
|
||||
"VALUES (#{jobId}, #{username}, #{password}, #{address}, #{phone}, #{email}, #{age}, #{signature}, #{avatar}, #{nickname}, #{accountNoLocked}, #{description}, #{updatedAt})")
|
||||
boolean insertUser(UserDO userDO);
|
||||
|
||||
@Select("select id, user_num, username, sex, age, unit, field, hometown, kind, state from organize_oa.oa_user where user_num = #{userNum} ")
|
||||
UserDO login(UserLoginVO userLoginVO);
|
||||
|
||||
@Select("select password from organize_oa.oa_user where user_num = #{userNum}")
|
||||
@Select("SELECT password FROM organize_oa.oa_user WHERE job_id = #{jobId}")
|
||||
String loginPassword(UserLoginVO userLoginVO);
|
||||
|
||||
@Select("SELECT * FROM organize_oa.oa_user WHERE job_id = #{jobId}")
|
||||
UserDO login(UserLoginVO userLoginVO);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import java.sql.Timestamp;
|
|||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class UserDO {
|
||||
private Long id;
|
||||
private Long jobId;
|
||||
private String jobId;
|
||||
private String username;
|
||||
private String password;
|
||||
private String address;
|
||||
|
|
|
@ -17,7 +17,7 @@ import javax.validation.constraints.Pattern;
|
|||
@Getter
|
||||
public class UserLoginVO {
|
||||
@Pattern(regexp = "^[0-9A-Z]+$", message = "工号格式错误")
|
||||
private String userNum;
|
||||
private String jobId;
|
||||
@NotBlank(message = "密码不能为空")
|
||||
private String password;
|
||||
}
|
||||
|
|
|
@ -23,11 +23,11 @@ public class UserRegisterVO {
|
|||
@NotBlank(message = "密码不能为空")
|
||||
private String password;
|
||||
|
||||
@Pattern(regexp = "^(男|女|保密)$", message = "性别只能为男、女或保密")
|
||||
private String sex;
|
||||
@Pattern(regexp = "^[012]$", message = "保密:0,男:1,女:2")
|
||||
private Short sex;
|
||||
|
||||
@NotBlank(message = "年龄不能为空")
|
||||
private String age;
|
||||
private Short age;
|
||||
|
||||
@NotBlank(message = "单位不能为空")
|
||||
private String unit;
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
package com.jsl.oa.services;
|
||||
|
||||
import org.apache.shiro.authc.Account;
|
||||
|
||||
public interface AccountService {
|
||||
Account findByUsername(String username);
|
||||
}
|
25
src/main/java/com/jsl/oa/services/UserService.java
Normal file
25
src/main/java/com/jsl/oa/services/UserService.java
Normal file
|
@ -0,0 +1,25 @@
|
|||
package com.jsl.oa.services;
|
||||
|
||||
import com.jsl.oa.model.doData.UserDO;
|
||||
|
||||
/**
|
||||
* <h1>用户控制器接口</h1>
|
||||
* <hr/>
|
||||
*
|
||||
* <p>该接口用于定义用户控制器的方法</p>
|
||||
*
|
||||
* @version 1.1.0
|
||||
* @since v1.1.0
|
||||
* @author 筱锋xiao_lfeng
|
||||
*/
|
||||
public interface UserService {
|
||||
/**
|
||||
* <h2>根据用户名获取用户信息</h2>
|
||||
*
|
||||
* <p>该方法用于根据用户名获取用户信息</p>
|
||||
*
|
||||
* @param username 用户名
|
||||
* @return 用户信息
|
||||
*/
|
||||
UserDO getUserInfoByUsername(String username);
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package com.jsl.oa.services.impl;
|
||||
|
||||
import com.jsl.oa.services.AccountService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.shiro.authc.Account;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class AccountServiceImpl implements AccountService {
|
||||
|
||||
private final AccountMapper accountMapper;
|
||||
|
||||
@Override
|
||||
public Account findByUsername(String username) {
|
||||
QueryWrapper wrapper = new QueryWrapper();
|
||||
wrapper.eq("username",username);
|
||||
return accountMapper.selectOne(wrapper);
|
||||
}
|
||||
}
|
|
@ -14,9 +14,7 @@ import lombok.RequiredArgsConstructor;
|
|||
import org.mindrot.jbcrypt.BCrypt;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
|
@ -33,9 +31,9 @@ public class AuthServiceImpl implements AuthService {
|
|||
* @throws ParseException 日期转换异常
|
||||
*/
|
||||
@Override
|
||||
public BaseResponse authRegister(UserRegisterVO userRegisterVO) throws ParseException {
|
||||
public BaseResponse authRegister(UserRegisterVO userRegisterVO) {
|
||||
// 用户检查是否存在
|
||||
UserDO getUserByUsername = userMapper.getUserByUsername(userRegisterVO.getUsername());
|
||||
UserDO getUserByUsername = userMapper.getUserInfoByUsername(userRegisterVO.getUsername());
|
||||
// 用户名已存在
|
||||
if (getUserByUsername != null) {
|
||||
return ResultUtil.error(ErrorCode.USER_EXIST);
|
||||
|
@ -46,20 +44,15 @@ public class AuthServiceImpl implements AuthService {
|
|||
do {
|
||||
userNum = Processing.createJobNumber((short) 2);
|
||||
} while (userMapper.getUserByUserNum(userNum) != null);
|
||||
// 处理性别
|
||||
|
||||
// 数据上传
|
||||
Date getDate = new Date(new SimpleDateFormat("yyyy-MM-dd").parse(userRegisterVO.getAge()).getTime());
|
||||
UserDO userDO = new UserDO();
|
||||
userDO.πsetUserNum(userNum)
|
||||
userDO.setJobId(userNum)
|
||||
.setUsername(userRegisterVO.getUsername())
|
||||
.setPassword(BCrypt.hashpw(userRegisterVO.getPassword(), BCrypt.gensalt()))
|
||||
.setSex(userRegisterVO.getSex())
|
||||
.setAge(getDate)
|
||||
.setUnit(userRegisterVO.getUnit())
|
||||
.setFiled(userRegisterVO.getFiled())
|
||||
.setHometown(userRegisterVO.getHometown())
|
||||
.setKind("0")
|
||||
.setState("0");
|
||||
.setAge(userRegisterVO.getAge());
|
||||
// 插入数据
|
||||
if (userMapper.insertUser(userDO)) {
|
||||
userDO.setPassword(null);
|
||||
|
|
19
src/main/java/com/jsl/oa/services/impl/UserServiceImpl.java
Normal file
19
src/main/java/com/jsl/oa/services/impl/UserServiceImpl.java
Normal file
|
@ -0,0 +1,19 @@
|
|||
package com.jsl.oa.services.impl;
|
||||
|
||||
import com.jsl.oa.dao.UserDAO;
|
||||
import com.jsl.oa.model.doData.UserDO;
|
||||
import com.jsl.oa.services.UserService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class UserServiceImpl implements UserService {
|
||||
|
||||
private final UserDAO userDAO;
|
||||
|
||||
@Override
|
||||
public UserDO getUserInfoByUsername(String username) {
|
||||
return userDAO.getUserInfoByUsername(username);
|
||||
}
|
||||
}
|
49
src/main/java/com/jsl/oa/utils/JwtUtil.java
Normal file
49
src/main/java/com/jsl/oa/utils/JwtUtil.java
Normal file
|
@ -0,0 +1,49 @@
|
|||
package com.jsl.oa.utils;
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jws;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
|
||||
import java.security.Key;
|
||||
|
||||
public class JwtUtil {
|
||||
// 替换为实际的密钥,建议使用足够长的随机字符串
|
||||
private static final String SECRET_KEY = Processing.createJobNumber((short) 1, (short) 255);
|
||||
|
||||
// Token 有效期,这里设置为一天,可以根据实际需求调整
|
||||
private static final long EXPIRATION_TIME = 86400000;
|
||||
|
||||
// 生成Token
|
||||
public static String generateToken(String username) {
|
||||
Key key = Keys.hmacShaKeyFor(SECRET_KEY.getBytes());
|
||||
|
||||
return Jwts.builder()
|
||||
.setSubject(username)
|
||||
.setExpiration(new java.util.Date(System.currentTimeMillis() + EXPIRATION_TIME))
|
||||
.signWith(key, SignatureAlgorithm.HS256)
|
||||
.compact();
|
||||
}
|
||||
|
||||
// 验证Token
|
||||
public static boolean verify(String token, String username) {
|
||||
try {
|
||||
Key key = Keys.hmacShaKeyFor(SECRET_KEY.getBytes());
|
||||
|
||||
Jws<Claims> claimsJws = Jwts.parserBuilder()
|
||||
.setSigningKey(key)
|
||||
.build()
|
||||
.parseClaimsJws(token);
|
||||
|
||||
// 从JWT中获取用户名进行匹配
|
||||
String tokenUsername = claimsJws.getBody().getSubject();
|
||||
|
||||
// 验证用户名是否匹配
|
||||
return username.equals(tokenUsername);
|
||||
} catch (Exception e) {
|
||||
// 验证失败
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package com.jsl.oa;
|
||||
|
||||
import com.jsl.oa.utils.JwtUtil;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
|
@ -8,6 +9,12 @@ class JslOrganizeInternalOaApplicationTests {
|
|||
|
||||
@Test
|
||||
void contextLoads() {
|
||||
String token = JwtUtil.generateToken("admin");
|
||||
if (JwtUtil.verify(token, "admin")) {
|
||||
System.out.println("验证通过");
|
||||
} else {
|
||||
System.out.println("验证失败");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user