禁用Session; 添加API Token授权与验证; 重写与调整Spring Security的一些组件; 添加认证服务(Auth)层; 添加JSON Token模型层; 完善用户层; 添加一些与API Token授权与认证有关的Exception;

This commit is contained in:
Saturneric 2020-03-15 19:18:51 +08:00
parent 0376be59eb
commit 2da6f6f8f8
30 changed files with 564 additions and 53 deletions

View File

@ -0,0 +1,14 @@
package com.codesdream.ase.component.auth;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.Optional;
@Component
public class AJAXRequestChecker {
public boolean checkAjaxPOSTRequest(HttpServletRequest request){
return Optional.ofNullable(request.getHeader("X-Requested-With")).isPresent();
}
}

View File

@ -0,0 +1,19 @@
package com.codesdream.ase.component.auth;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Date;
import java.util.UUID;
@Component
public class AuthTokenGenerator {
@Resource
private SHA1Encoder encoder;
public String generateAuthToken(String username){
Date dateNow = new Date();
UUID uuid = UUID.randomUUID();
return encoder.encode(String.format("Token [%s][%d][%s]",username,dateNow.getTime(), uuid.toString()));
}
}

View File

@ -0,0 +1,18 @@
package com.codesdream.ase.component.auth;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Date;
@Component
public class JSONRandomCodeGenerator {
@Resource
private SHA1Encoder encoder;
public String generateRandomCode(String username, Date date, String apiSHA1){
return encoder.encode(String.format("RandomCode [%s][%s][%s]",
username, date.toString(), apiSHA1));
}
}

View File

@ -0,0 +1,16 @@
package com.codesdream.ase.component.auth;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
// 用来给JSON生成签名
@Component
public class JSONSignedGenerator {
@Resource
SHA1Encoder encoder;
public String generateSigned(String username, String randomCode, String token){
return encoder.encode(String.format("SIGN [%s][%s][%s]",username, randomCode, token));
}
}

View File

@ -0,0 +1,58 @@
package com.codesdream.ase.component.auth;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
// 关联Token与其他用户的相关数据的认证对象
public class JSONTokenAuthenticationToken extends AbstractAuthenticationToken {
// token 产生的签名
String signed = null;
// 用户名
Object principal = null;
// JSON 特征随机代码
String randomCode = null;
/**
* Creates a token with the supplied array of authorities.
*
* @param authorities the collection of <tt>GrantedAuthority</tt>s for the principal
* represented by this authentication object.
*/
public JSONTokenAuthenticationToken(UserDetails principal, String signed, Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
this.randomCode = null;
this.signed = signed;
setAuthenticated(true);
}
public JSONTokenAuthenticationToken(String principal, String randomCode, String signed) {
super(null);
this.principal = principal;
this.randomCode = randomCode;
this.signed = signed;
setAuthenticated(false);
}
@Override
public String getCredentials() {
return signed;
}
@Override
public Object getPrincipal() {
return principal;
}
public String getRandomCode() {
return randomCode;
}
public void setRandomCode(String randomCode) {
this.randomCode = randomCode;
}
}

View File

@ -0,0 +1,17 @@
package com.codesdream.ase.component.auth;
import org.apache.commons.codec.cli.Digest;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Component;
// SHA1算法不可逆加密 主要用于JSON签名
@Component
public class SHA1Encoder {
String encode(CharSequence charSequence){
return DigestUtils.sha1Hex(charSequence.toString());
}
boolean match(CharSequence charSequence, String s){
return s.equals(encode(charSequence));
}
}

View File

@ -19,7 +19,13 @@ public class JSONParameter {
// 处理Request Body
public String getRequestBody(HttpServletRequest request){
try {
return request.getParameter("json");
StringBuilder stringBuilder = new StringBuilder();
BufferedReader reader = request.getReader();
reader.reset();
String line;
while ((line = reader.readLine()) != null)
stringBuilder.append(line);
return stringBuilder.toString();
} catch (Exception e) {
e.printStackTrace();
return null;

View File

@ -0,0 +1,12 @@
package com.codesdream.ase.component.json;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
// 所有有效的JSON对象模板
@Slf4j
public class JSONBaseObject {
Date time = new Date();
}

View File

@ -0,0 +1,13 @@
package com.codesdream.ase.component.json.request;
import com.codesdream.ase.component.json.JSONBaseObject;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
// 客户端请求的JSON模板
@Slf4j
public class JSONBaseRequestObject extends JSONBaseObject {
String signed;
}

View File

@ -4,7 +4,13 @@ import lombok.Data;
@Data
public class UserLoginChecker {
// 请求类型
private String checkType;
private String username;
private String password;
// // 客户端类型
// private String clientType;
// // JSON签名
// private String signed;
}

View File

@ -1,16 +1,15 @@
package com.codesdream.ase.component.json.respond;
import com.codesdream.ase.component.json.JSONBaseObject;
import lombok.Data;
import java.util.Date;
// 服务端返回的JSON对象基础信息
// 服务端返回的JSON对象模板
@Data
public class JSONBaseRespondObject {
public class JSONBaseRespondObject extends JSONBaseObject {
// 请求成功状态
String status = "fail";
// 时间
Date time = new Date();
public JSONBaseRespondObject(){

View File

@ -10,7 +10,7 @@ public class UserLoginCheckerJSONRespond extends JSONBaseRespondObject {
boolean loginStatus = false;
boolean userBanned = false;
String respondInformation = "";
String sessionId = "";
String token = "";
public UserLoginCheckerJSONRespond(){
super("success");

View File

@ -0,0 +1,6 @@
package com.codesdream.ase.component.json.respond;
// 返回登录后的授权码(用于客户端生成签名)
public class UserLoginTokenJSONRespond extends JSONBaseRespondObject {
String token;
}

View File

@ -25,7 +25,7 @@ public class ASEAuthenticationFailureHandler extends SimpleUrlAuthenticationFail
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)
throws IOException, ServletException
{
log.info("ASEAuthenticationSuccessHandler Login Fail!");
log.info("ASEAuthenticationFailureHandler Login Fail!");
UserLoginCheckerJSONRespond respond = new UserLoginCheckerJSONRespond();
respond.setUserExist(false);
respond.setLoginStatus(false);

View File

@ -3,12 +3,14 @@ package com.codesdream.ase.component.permission;
import com.codesdream.ase.component.datamanager.JSONParameter;
import com.codesdream.ase.component.json.respond.UserLoginCheckerJSONRespond;
import com.codesdream.ase.model.permission.User;
import com.codesdream.ase.service.IAuthService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@ -26,29 +28,36 @@ public class ASEAuthenticationSuccessHandler extends SavedRequestAwareAuthentica
@Resource
private JSONParameter jsonParameter;
@Resource
private IAuthService authService;
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, ServletException
{
// 对AJAX登录请求特殊化处理
/*
if(Optional.ofNullable(request.getHeader("X-Requested-With")).isPresent()) {
HttpSession session = request.getSession();
SecurityContext securityContext = SecurityContextHolder.getContext();
session.setAttribute("SPRING_SECURITY_CONTEXT", securityContext);
}
// 打印用户登录成功日志
log.info(String.format("ASEAuthenticationSuccessHandler: %s Login Success.",
((User)authentication.getDetails()).getUsername()));
*/
UserLoginCheckerJSONRespond respond = new UserLoginCheckerJSONRespond();
respond.setUserExist(authentication.isAuthenticated());
respond.setLoginStatus(authentication.isAuthenticated());
// 获得session id
WebAuthenticationDetails webAuthenticationDetails = (WebAuthenticationDetails) (authentication.getDetails());
respond.setSessionId(webAuthenticationDetails.getSessionId());
/*WebAuthenticationDetails webAuthenticationDetails = (WebAuthenticationDetails) (authentication.getDetails());*/
User user = (User) authentication.getPrincipal();
// 获得api token
Optional<String> tokenOptional = authService.userNewTokenGetter(user.getUsername());
if(tokenOptional.isPresent()){
respond.setToken(tokenOptional.get());
}
else respond.setToken("");
response.getWriter().write(jsonParameter.getJSONString(respond));

View File

@ -0,0 +1,119 @@
package com.codesdream.ase.component.permission;
import com.alibaba.fastjson.JSONObject;
import com.codesdream.ase.component.auth.AJAXRequestChecker;
import com.codesdream.ase.component.auth.JSONRandomCodeGenerator;
import com.codesdream.ase.component.auth.JSONSignedGenerator;
import com.codesdream.ase.component.auth.JSONTokenAuthenticationToken;
import com.codesdream.ase.component.datamanager.JSONParameter;
import com.codesdream.ase.exception.JSONTokenExpiredException;
import com.codesdream.ase.exception.JSONTokenIncorrectSignedException;
import com.codesdream.ase.model.auth.JSONToken;
import com.codesdream.ase.service.AuthService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.file.attribute.UserPrincipalNotFoundException;
import java.util.Collection;
import java.util.Date;
import java.util.Optional;
// API请求验证过滤
@Slf4j
public class ASEJSONTokenAuthenticationFilter extends OncePerRequestFilter {
@Resource
private JSONParameter jsonParameter;
@Resource
private JSONRandomCodeGenerator randomCodeGenerator;
@Resource
private AJAXRequestChecker ajaxRequestChecker;
@Resource
private AuthService authService;
@Resource
private JSONSignedGenerator signedGenerator;
@Resource
private UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String username = request.getHeader( "username");
String signed = request.getHeader("signed");
String rawDate = request.getHeader("date");
// 对API的内容取哈希码
String apiSHA1 = request.getHeader("apiSHA1");
if (signed != null && username != null && rawDate != null && apiSHA1 != null) {
// 获得具体时间
Date date = new Date(Long.parseLong(rawDate));
// 检查时间是否合理
// ...
// 生成特征随机代码
String randomCode = randomCodeGenerator.generateRandomCode(username, date, apiSHA1);
// 进行验证
Optional<JSONToken> optionalJSONToken = authService.findTokenByUserName(username);
if(!optionalJSONToken.isPresent()){
throw new UserPrincipalNotFoundException("Token Not Found");
}
// 检查token是否过期
JSONToken token = optionalJSONToken.get();
if(!authService.checkTokenIfExpired(token)) {
log.info(String.format("Determined Signed: %s",
signedGenerator.generateSigned(username, randomCode, token.getToken())));
// 检查签名是否正确
if (signed.equals(signedGenerator.generateSigned(username, randomCode, token.getToken()))) {
// 查询用户的相关信息
UserDetails user = userDetailsService.loadUserByUsername(username);
Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
// 生成认证柄 (储存上下文信息)
JSONTokenAuthenticationToken authentication = new JSONTokenAuthenticationToken(user, signed, authorities);
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
filterChain.doFilter(request, response);
}
}

View File

@ -14,6 +14,7 @@ import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Collection;
// 普通用户名密码验证, 用户获得Token
@Slf4j
@Component
public class ASESecurityAuthenticationProvider implements AuthenticationProvider {
@ -63,6 +64,6 @@ public class ASESecurityAuthenticationProvider implements AuthenticationProvider
@Override
public boolean supports(Class<?> aClass) {
return true;
return aClass.equals(UsernamePasswordAuthenticationToken.class);
}
}

View File

@ -1,5 +1,6 @@
package com.codesdream.ase.component.permission;
import com.codesdream.ase.component.auth.AJAXRequestChecker;
import com.codesdream.ase.component.datamanager.JSONParameter;
import com.codesdream.ase.component.json.request.UserLoginChecker;
import lombok.extern.slf4j.Slf4j;
@ -22,41 +23,45 @@ public class ASEUsernamePasswordAuthenticationFilter extends UsernamePasswordAut
@Resource
private JSONParameter jsonParameter;
@Resource
private AJAXRequestChecker ajaxRequestChecker;
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
// 判断是否为AJAX请求格式的数据
if(Optional.ofNullable(request.getHeader("X-Requested-With")).isPresent()) {
Optional<UserLoginChecker> checker = jsonParameter.getJavaObjectByRequest(request, UserLoginChecker.class);
if(!checker.isPresent()) throw new BadCredentialsException("Invalid AJAX JSON Request");
if (!checker.get().getCheckType().equals("From"))
throw new AuthenticationServiceException("Invalid Checker Type");
// 获得相应的用户名密码
String username = checker.get().getUsername();
String password = checker.get().getPassword();
if (username == null) username = "";
if (password == null) password = "";
// 去除首尾两端的空白字符
username = username.trim();
password = password.trim();
UsernamePasswordAuthenticationToken authRequest =
new UsernamePasswordAuthenticationToken(username, password);
log.info(String.format("User AJAX JSON Authentication: %s %s.", username, password));
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
else{
return super.attemptAuthentication(request, response);
if(!ajaxRequestChecker.checkAjaxPOSTRequest(request)) {
log.info("NOT AJAX POST Request.");
throw new AuthenticationServiceException("Authentication method not supported: NOT Ajax Method.");
}
Optional<UserLoginChecker> checker = jsonParameter.getJavaObjectByRequest(request, UserLoginChecker.class);
if(!checker.isPresent()) throw new BadCredentialsException("Invalid AJAX JSON Request");
log.info("JSON Object 2 Java Object Success.");
if (!checker.get().getCheckType().equals("UsernamePasswordChecker"))
throw new AuthenticationServiceException("Authentication not supported: NOT Username Password Type.");
// 获得相应的用户名密码
String username = checker.get().getUsername();
String password = checker.get().getPassword();
if (username == null) username = "";
if (password == null) password = "";
// 去除首尾两端的空白字符
username = username.trim();
password = password.trim();
UsernamePasswordAuthenticationToken authRequest =
new UsernamePasswordAuthenticationToken(username, password);
log.info(String.format("User AJAX JSON Authentication: %s %s.", username, password));
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
}

View File

@ -4,6 +4,7 @@ import com.codesdream.ase.component.permission.*;
import com.codesdream.ase.service.ASEUserDetailsService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
@ -51,6 +52,7 @@ public class CustomWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
ASEAccessDeniedHandler accessDeniedHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
@ -66,7 +68,9 @@ public class CustomWebSecurityConfig extends WebSecurityConfigurerAdapter {
// 替换掉原有的UsernamePasswordAuthenticationFilter
http.addFilterAt(aseUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.addFilterAfter(new SecurityContextPersistenceFilter(), UsernamePasswordAuthenticationFilter.class);
.addFilterBefore(asejsonTokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@ -90,6 +94,12 @@ public class CustomWebSecurityConfig extends WebSecurityConfigurerAdapter {
"/login/**");
}
//注册自定义的UsernamePasswordAuthenticationFilter
@Bean
ASEJSONTokenAuthenticationFilter asejsonTokenAuthenticationFilter() throws Exception {
return new ASEJSONTokenAuthenticationFilter();
}
//注册自定义的UsernamePasswordAuthenticationFilter
@Bean
ASEUsernamePasswordAuthenticationFilter aseUsernamePasswordAuthenticationFilter() throws Exception {
@ -99,7 +109,7 @@ public class CustomWebSecurityConfig extends WebSecurityConfigurerAdapter {
filter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy(sessionRegistry()));
filter.setAllowSessionCreation(true);
filter.setRequiresAuthenticationRequestMatcher(
new AntPathRequestMatcher("/login/process", "POST"));
new AntPathRequestMatcher("/login/token", "POST"));
filter.setAuthenticationManager(authenticationManagerBean());
return filter;

View File

@ -0,0 +1,14 @@
package com.codesdream.ase.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class APIController {
@RequestMapping("hello")
String hello(){
return "hello";
}
}

View File

@ -18,6 +18,7 @@ import java.util.List;
@Controller
public class ASEErrorController implements ErrorController {
@RequestMapping("/error")
public String handleError(HttpServletRequest request, Model model){
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");

View File

@ -17,6 +17,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.security.Principal;
import java.util.Optional;
@ -41,9 +42,9 @@ public class LoginController {
return "login";
}
@RequestMapping(value = "/login/check", method = RequestMethod.POST)
@RequestMapping(value = "/login/check_exists", method = RequestMethod.POST)
@ResponseBody
String checkLogin(HttpServletRequest request){
String checkExists(HttpServletRequest request){
// 检查是否为JSON
Optional<JSONObject> json = jsonParameter.getJSONByRequest(request);
@ -51,10 +52,11 @@ public class LoginController {
UserLoginChecker loginChecker = json.get().toJavaObject(UserLoginChecker.class);
// 检查类型
// 检查学号对应的用户名是否存在
if(loginChecker.getCheckType().equals("UsernameExistChecker")){
// 根据学号计算用户名
String user = usernameEncoder.encode(loginChecker.getUsername()) ;
String user = userService.getUsernameByStudentId(loginChecker.getUsername());
// 查询用户名存在状态
boolean existStatus = userService.checkIfUserExists(user).getKey();
// 构造返回对象
@ -68,4 +70,29 @@ public class LoginController {
}
}
// 根据学号计算对应的username
@RequestMapping(value = "/login/check_uid", method = RequestMethod.POST)
@ResponseBody
String checkUsernameByStudentID(HttpServletRequest request){
// 检查是否为JSON
Optional<JSONObject> json = jsonParameter.getJSONByRequest(request);
if(!json.isPresent()) return jsonParameter.getJSONString(new FailedSONRespond());
UserLoginChecker loginChecker = json.get().toJavaObject(UserLoginChecker.class);
if(loginChecker.getCheckType().equals("UIDGeneratorChecker")) {
UserLoginCheckerJSONRespond respond = new UserLoginCheckerJSONRespond();
respond.setRespondInformation(userService.getUsernameByStudentId(loginChecker.getUsername()));
return jsonParameter.getJSONString(respond);
}
else {
// 返回失败对象
return jsonParameter.getJSONString(new JSONBaseRespondObject());
}
}
}

View File

@ -0,0 +1,9 @@
package com.codesdream.ase.exception;
import org.springframework.security.core.AuthenticationException;
public class JSONTokenExpiredException extends AuthenticationException {
public JSONTokenExpiredException(String msg) {
super(msg);
}
}

View File

@ -0,0 +1,10 @@
package com.codesdream.ase.exception;
import org.springframework.security.core.AuthenticationException;
public class JSONTokenIncorrectSignedException extends AuthenticationException {
public JSONTokenIncorrectSignedException(String msg) {
super(msg);
}
}

View File

@ -0,0 +1,28 @@
package com.codesdream.ase.model.auth;
import lombok.Data;
import javax.persistence.*;
import java.util.Date;
// token记录
@Data
@Entity
@Table(name = "json_tokens")
public class JSONToken {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
// token对应的用户
@Column(unique = true)
private String username;
// token值
@Column(unique = true)
private String token;
// token过期时间
private Date expiredDate;
}

View File

@ -0,0 +1,12 @@
package com.codesdream.ase.repository.auth;
import com.codesdream.ase.model.auth.JSONToken;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface JSONTokenRepository extends CrudRepository<JSONToken, Integer> {
Optional<JSONToken> findByUsername(String username);
}

View File

@ -0,0 +1,57 @@
package com.codesdream.ase.service;
import com.codesdream.ase.component.auth.AuthTokenGenerator;
import com.codesdream.ase.model.auth.JSONToken;
import com.codesdream.ase.model.permission.User;
import com.codesdream.ase.repository.auth.JSONTokenRepository;
import com.sun.org.apache.xpath.internal.operations.Bool;
import javafx.util.Pair;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Date;
import java.util.Optional;
// 认证服务
@Service
public class AuthService implements IAuthService {
@Resource
private JSONTokenRepository jsonTokenRepository;
@Resource
private IUserService userService;
@Resource
private AuthTokenGenerator authTokenGenerator;
@Override
public Optional<JSONToken> findTokenByUserName(String username) {
return jsonTokenRepository.findByUsername(username);
}
@Override
public boolean checkTokenIfExpired(JSONToken token) {
return token.getExpiredDate().compareTo(new Date()) <= 0;
}
@Override
public Optional<String> userNewTokenGetter(String username) {
Pair<Boolean, User> userPair = userService.checkIfUserExists(username);
if(userPair.getKey()){
Optional<JSONToken> jsonTokenOptional = jsonTokenRepository.findByUsername(username);
JSONToken token = jsonTokenOptional.orElseGet(JSONToken::new);
// 过期时间设置为三十分钟后
long currentTime = System.currentTimeMillis();
currentTime +=30*60*1000;
token.setExpiredDate(new Date(currentTime));
token.setToken(authTokenGenerator.generateAuthToken(username));
// 设置用户名
token.setUsername(username);
// 在数据库中更新新的token
token = jsonTokenRepository.save(token);
return Optional.ofNullable(token.getToken());
}
else return Optional.empty();
}
}

View File

@ -0,0 +1,16 @@
package com.codesdream.ase.service;
import com.codesdream.ase.model.auth.JSONToken;
import java.util.Optional;
public interface IAuthService {
// 通过用户名查找与对应用户相关联的token
Optional<JSONToken> findTokenByUserName(String username);
// 检查token是否过期
boolean checkTokenIfExpired(JSONToken token);
// 为用户获得一个新的API Token
Optional<String> userNewTokenGetter(String username);
}

View File

@ -24,6 +24,7 @@ public interface IUserService {
User findUserByUsername(String username);
// 查询用户是否存在
public Pair<Boolean, User> checkIfUserExists(String username);
// 获得用户所有的权限角色
@ -38,6 +39,9 @@ public interface IUserService {
// 根据学号生成随机用户名
void generateRandomUsernameByStudentID(User user, String id);
// 更具学号获得对应的用户名
String getUsernameByStudentId(String studentId);
// 随机生成一个用户名
void generateRandomUsername(User user);

View File

@ -81,6 +81,11 @@ public class UserService implements IUserService {
user.setUsername(usernameEncoder.encode(id));
}
@Override
public String getUsernameByStudentId(String studentId) {
return usernameEncoder.encode(studentId);
}
@Override
public void generateRandomUsername(User user) {
user.setUsername(usernameEncoder.encode(UUID.randomUUID().toString()));