Bladeren bron

login api

deason 1 jaar geleden
bovenliggende
commit
b5c295f97f

+ 59 - 0
src/main/java/com/qmth/exam/reserve/bean/login/LoginUser.java

@@ -0,0 +1,59 @@
+package com.qmth.exam.reserve.bean.login;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.qmth.boot.core.security.model.AccessEntity;
+import com.qmth.exam.reserve.bean.IModel;
+import com.qmth.exam.reserve.enums.Role;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class LoginUser implements AccessEntity, IModel {
+
+    private static final long serialVersionUID = 8254087838589213068L;
+
+    @ApiModelProperty(value = "学校ID")
+    private Long orgId;
+
+    @ApiModelProperty(value = "用户ID")
+    private Long id;
+
+    @ApiModelProperty(value = "账号")
+    private String account;
+
+    @ApiModelProperty(value = "用户姓名")
+    private String name;
+
+    @ApiModelProperty(value = "角色")
+    private Role role;
+
+    @ApiModelProperty(value = "鉴权信息")
+    private String sessionId;
+
+    @ApiModelProperty(value = "鉴权信息")
+    private String token;
+
+    @Override
+    @JsonIgnore
+    @ApiModelProperty(hidden = true)
+    public String getIdentity() {
+        return sessionId;
+    }
+
+    @Override
+    @JsonIgnore
+    @ApiModelProperty(hidden = true)
+    public String getSecret() {
+        return token;
+    }
+
+    @Override
+    @JsonIgnore
+    @ApiModelProperty(hidden = true)
+    public String getLogName() {
+        return role + " | " + account + " | uid_" + id;
+    }
+
+}

+ 0 - 32
src/main/java/com/qmth/exam/reserve/bean/login/SessionUser.java

@@ -1,32 +0,0 @@
-package com.qmth.exam.reserve.bean.login;
-
-import com.qmth.exam.reserve.bean.IModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Getter;
-import lombok.Setter;
-
-@Getter
-@Setter
-public class SessionUser implements IModel {
-
-    private static final long serialVersionUID = 8254087838589213068L;
-
-    @ApiModelProperty(value = "学校ID")
-    private Long orgId;
-
-    @ApiModelProperty(value = "用户ID")
-    private Long id;
-
-    @ApiModelProperty(value = "用户姓名")
-    private String name;
-
-    @ApiModelProperty(value = "角色")
-    private String role;
-
-    @ApiModelProperty(value = "鉴权信息")
-    private String sessionId;
-
-    @ApiModelProperty(value = "鉴权信息")
-    private String token;
-
-}

+ 15 - 0
src/main/java/com/qmth/exam/reserve/cache/CacheHelper.java

@@ -0,0 +1,15 @@
+package com.qmth.exam.reserve.cache;
+
+import com.github.benmanes.caffeine.cache.Cache;
+import com.github.benmanes.caffeine.cache.Caffeine;
+import com.qmth.exam.reserve.bean.login.LoginUser;
+
+import java.util.concurrent.TimeUnit;
+
+public class CacheHelper {
+
+    public static final Cache<String, LoginUser> LOGIN_SESSION = Caffeine.newBuilder()
+            .expireAfterWrite(60, TimeUnit.MINUTES).build();
+
+
+}

+ 22 - 0
src/main/java/com/qmth/exam/reserve/cache/LoginSessionManager.java

@@ -0,0 +1,22 @@
+package com.qmth.exam.reserve.cache;
+
+import com.qmth.exam.reserve.bean.login.LoginUser;
+
+/**
+ * 在线登录用户会话管理
+ */
+public class LoginSessionManager {
+
+    public static LoginUser getLoginSession(String sessionId) {
+        return null;
+    }
+
+    public static void addLoginSession(LoginUser session) {
+        CacheHelper.LOGIN_SESSION.put(session.getSessionId(), session);
+    }
+
+    public static void removeLoginSession(String sessionId) {
+        CacheHelper.LOGIN_SESSION.invalidate(sessionId);
+    }
+
+}

+ 14 - 4
src/main/java/com/qmth/exam/reserve/controller/BaseController.java

@@ -1,7 +1,9 @@
 package com.qmth.exam.reserve.controller;
 
+import com.qmth.boot.api.constant.ApiConstant;
 import com.qmth.boot.core.exception.StatusException;
 import com.qmth.boot.tools.io.IOUtils;
+import com.qmth.exam.reserve.bean.login.LoginUser;
 import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 
@@ -13,12 +15,20 @@ import java.util.Objects;
 
 public class BaseController {
 
-    protected HttpServletRequest currentRequest() {
+    protected LoginUser curLoginUser() {
+        LoginUser user = (LoginUser) this.curRequest().getAttribute(ApiConstant.ATTRIBUTE_ACCESS_ENTITY);
+        if (user == null) {
+            throw new StatusException("请先登录!");
+        }
+        return user;
+    }
+
+    protected HttpServletRequest curRequest() {
         return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes()))
                 .getRequest();
     }
 
-    protected HttpServletResponse currentResponse() {
+    protected HttpServletResponse curResponse() {
         return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes()))
                 .getResponse();
     }
@@ -29,7 +39,7 @@ public class BaseController {
         try {
             in = new FileInputStream(file);
             fileName = URLEncoder.encode(fileName, "UTF-8");
-            HttpServletResponse response = currentResponse();
+            HttpServletResponse response = curResponse();
             response.reset();
             response.setHeader("Content-Disposition", "inline; filename=" + fileName);
             response.addHeader("Content-Length", "" + file.length());
@@ -49,7 +59,7 @@ public class BaseController {
         OutputStream out = null;
         try {
             fileName = URLEncoder.encode(fileName, "UTF-8");
-            HttpServletResponse response = currentResponse();
+            HttpServletResponse response = curResponse();
             response.reset();
             response.setHeader("Content-Disposition", "inline; filename=" + fileName);
             response.setContentType("application/octet-stream;charset=UTF-8");

+ 9 - 6
src/main/java/com/qmth/exam/reserve/controller/admin/UserLoginController.java

@@ -3,12 +3,14 @@ package com.qmth.exam.reserve.controller.admin;
 import com.qmth.boot.api.annotation.Aac;
 import com.qmth.boot.api.constant.ApiConstant;
 import com.qmth.exam.reserve.bean.login.LoginReq;
-import com.qmth.exam.reserve.bean.login.SessionUser;
+import com.qmth.exam.reserve.bean.login.LoginUser;
 import com.qmth.exam.reserve.controller.BaseController;
+import com.qmth.exam.reserve.service.AuthService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -22,19 +24,20 @@ public class UserLoginController extends BaseController {
 
     private static final Logger log = LoggerFactory.getLogger(UserLoginController.class);
 
+    @Autowired
+    private AuthService authService;
+
     @ApiOperation(value = "用户登录(账号)")
     @PostMapping(value = "/login")
-    public SessionUser login(@RequestBody LoginReq req) {
-        SessionUser user = new SessionUser();
-        //todo
-        return user;
+    public LoginUser login(@RequestBody LoginReq req) {
+        return authService.userLogin(req);
     }
 
     @Aac(strict = false, auth = true)
     @ApiOperation(value = "用户登出")
     @PostMapping(value = "/logout")
     public void logout() {
-        //todo
+        authService.logout(curLoginUser());
     }
 
 }

+ 11 - 10
src/main/java/com/qmth/exam/reserve/controller/student/StudentLoginController.java

@@ -3,13 +3,15 @@ package com.qmth.exam.reserve.controller.student;
 import com.qmth.boot.api.annotation.Aac;
 import com.qmth.boot.api.constant.ApiConstant;
 import com.qmth.exam.reserve.bean.login.LoginReq;
-import com.qmth.exam.reserve.bean.login.SessionUser;
+import com.qmth.exam.reserve.bean.login.LoginUser;
 import com.qmth.exam.reserve.bean.login.WechatLoginReq;
 import com.qmth.exam.reserve.controller.BaseController;
+import com.qmth.exam.reserve.service.AuthService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -23,27 +25,26 @@ public class StudentLoginController extends BaseController {
 
     private static final Logger log = LoggerFactory.getLogger(StudentLoginController.class);
 
+    @Autowired
+    private AuthService authService;
+
     @ApiOperation(value = "考生登录(账号)")
     @PostMapping(value = "/login")
-    public SessionUser login(@RequestBody LoginReq req) {
-        SessionUser user = new SessionUser();
-        //todo
-        return user;
+    public LoginUser login(@RequestBody LoginReq req) {
+        return authService.studentLogin(req);
     }
 
     @ApiOperation(value = "考生登录(微信号)")
     @PostMapping(value = "/login/for/wechat")
-    public SessionUser loginForWechat(@RequestBody WechatLoginReq req) {
-        SessionUser user = new SessionUser();
-        //todo
-        return user;
+    public LoginUser loginForWechat(@RequestBody WechatLoginReq req) {
+        return authService.wechatLogin(req);
     }
 
     @Aac(strict = false, auth = true)
     @ApiOperation(value = "考生登出")
     @PostMapping(value = "/logout")
     public void logout() {
-        //todo
+        authService.logout(curLoginUser());
     }
 
 }

+ 8 - 0
src/main/java/com/qmth/exam/reserve/dao/StudentDao.java

@@ -0,0 +1,8 @@
+package com.qmth.exam.reserve.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.qmth.exam.reserve.entity.StudentEntity;
+
+public interface StudentDao extends BaseMapper<StudentEntity> {
+
+}

+ 4 - 1
src/main/java/com/qmth/exam/reserve/enums/Role.java

@@ -6,7 +6,9 @@ public enum Role {
 
     ADMIN("学校管理员"),
 
-    TEACHING("教学点管理员");
+    TEACHING("教学点管理员"),
+
+    STUDENT("学生");
 
     private String title;
 
@@ -25,6 +27,7 @@ public enum Role {
                 return r;
             }
         }
+
         return null;
     }
 

+ 17 - 0
src/main/java/com/qmth/exam/reserve/service/AuthService.java

@@ -0,0 +1,17 @@
+package com.qmth.exam.reserve.service;
+
+import com.qmth.exam.reserve.bean.login.LoginReq;
+import com.qmth.exam.reserve.bean.login.LoginUser;
+import com.qmth.exam.reserve.bean.login.WechatLoginReq;
+
+public interface AuthService {
+
+    LoginUser userLogin(LoginReq req);
+
+    LoginUser studentLogin(LoginReq req);
+
+    LoginUser wechatLogin(WechatLoginReq req);
+
+    void logout(LoginUser user);
+
+}

+ 10 - 0
src/main/java/com/qmth/exam/reserve/service/StudentService.java

@@ -0,0 +1,10 @@
+package com.qmth.exam.reserve.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.exam.reserve.entity.StudentEntity;
+
+public interface StudentService extends IService<StudentEntity> {
+
+    StudentEntity findStudentByStudentCode(Long orgId, String studentCode);
+
+}

+ 2 - 0
src/main/java/com/qmth/exam/reserve/service/UserService.java

@@ -5,4 +5,6 @@ import com.qmth.exam.reserve.entity.UserEntity;
 
 public interface UserService extends IService<UserEntity> {
 
+    UserEntity findUserByLoginName(Long orgId, String loginName);
+
 }

+ 125 - 0
src/main/java/com/qmth/exam/reserve/service/impl/AuthServiceImpl.java

@@ -0,0 +1,125 @@
+package com.qmth.exam.reserve.service.impl;
+
+import com.qmth.boot.core.exception.StatusException;
+import com.qmth.boot.core.security.annotation.AuthorizationComponent;
+import com.qmth.boot.core.security.service.AuthorizationService;
+import com.qmth.boot.tools.signature.SignatureType;
+import com.qmth.boot.tools.uuid.FastUUID;
+import com.qmth.exam.reserve.bean.login.LoginReq;
+import com.qmth.exam.reserve.bean.login.LoginUser;
+import com.qmth.exam.reserve.bean.login.WechatLoginReq;
+import com.qmth.exam.reserve.cache.LoginSessionManager;
+import com.qmth.exam.reserve.entity.StudentEntity;
+import com.qmth.exam.reserve.entity.UserEntity;
+import com.qmth.exam.reserve.enums.Role;
+import com.qmth.exam.reserve.service.AuthService;
+import com.qmth.exam.reserve.service.StudentService;
+import com.qmth.exam.reserve.service.UserService;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+@AuthorizationComponent
+public class AuthServiceImpl implements AuthorizationService<LoginUser>, AuthService {
+
+    private final static Logger log = LoggerFactory.getLogger(AuthServiceImpl.class);
+
+    @Autowired
+    private UserService userService;
+
+    @Autowired
+    private StudentService studentService;
+
+    @Override
+    public LoginUser userLogin(LoginReq req) {
+        if (StringUtils.isBlank(req.getAccount())) {
+            throw new StatusException("登录账号不能为空");
+        }
+
+        if (StringUtils.isBlank(req.getPassword())) {
+            throw new StatusException("登录密码不能为空");
+        }
+
+        log.info("[USER_LOGIN] account:{}", req.getAccount());
+        UserEntity user = userService.findUserByLoginName(req.getOrgId(), req.getAccount());
+        if (user == null) {
+            throw new StatusException("登录用户不存在");
+        }
+
+        String encodePassword = DigestUtils.sha256Hex(req.getPassword()).toUpperCase();
+        if (!encodePassword.equals(user.getPassword())) {
+            throw new StatusException("登录账号或密码错误");
+        }
+
+        LoginUser loginUser = new LoginUser();
+        loginUser.setId(user.getId());
+        loginUser.setOrgId(user.getOrgId());
+        loginUser.setAccount(user.getLoginName());
+        loginUser.setName(user.getName());
+        loginUser.setRole(user.getRole());
+
+        loginUser.setSessionId("U_" + user.getId());
+        loginUser.setToken(FastUUID.get());
+        LoginSessionManager.addLoginSession(loginUser);
+
+        log.info("[USER_LOGIN] account:{} {} {}", loginUser.getAccount(), loginUser.getName(), loginUser.getRole());
+        return loginUser;
+    }
+
+    @Override
+    public LoginUser studentLogin(LoginReq req) {
+        if (StringUtils.isBlank(req.getAccount())) {
+            throw new StatusException("登录账号不能为空");
+        }
+
+        if (StringUtils.isBlank(req.getPassword())) {
+            throw new StatusException("登录密码不能为空");
+        }
+
+        log.info("[STUDENT_LOGIN] account:{}", req.getAccount());
+        StudentEntity student = studentService.findStudentByStudentCode(req.getOrgId(), req.getAccount());
+        if (student == null) {
+            throw new StatusException("登录用户不存在");
+        }
+
+        String encodePassword = DigestUtils.sha256Hex(req.getPassword()).toUpperCase();
+        if (!encodePassword.equals(student.getPassword())) {
+            throw new StatusException("登录账号或密码错误");
+        }
+
+        LoginUser loginUser = new LoginUser();
+        loginUser.setId(student.getId());
+        loginUser.setOrgId(student.getOrgId());
+        loginUser.setAccount(student.getStudentCode());
+        loginUser.setName(student.getName());
+        loginUser.setRole(Role.STUDENT);
+
+        loginUser.setSessionId("S_" + student.getId());
+        loginUser.setToken(FastUUID.get());
+        LoginSessionManager.addLoginSession(loginUser);
+
+        log.info("[STUDENT_LOGIN] account:{} {}", loginUser.getAccount(), loginUser.getName());
+        return loginUser;
+    }
+
+    @Override
+    public LoginUser wechatLogin(WechatLoginReq req) {
+        return null;
+    }
+
+    @Override
+    public void logout(LoginUser loginUser) {
+        LoginSessionManager.removeLoginSession(loginUser.getSessionId());
+        log.warn("用户退出登录!account:{},{}", loginUser.getAccount(), loginUser.getName());
+    }
+
+    @Override
+    public LoginUser findByIdentity(String identity, SignatureType type, String path) {
+        return LoginSessionManager.getLoginSession(identity);
+    }
+
+}

+ 27 - 0
src/main/java/com/qmth/exam/reserve/service/impl/StudentServiceImpl.java

@@ -0,0 +1,27 @@
+package com.qmth.exam.reserve.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.exam.reserve.dao.StudentDao;
+import com.qmth.exam.reserve.entity.StudentEntity;
+import com.qmth.exam.reserve.service.StudentService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+@Service
+public class StudentServiceImpl extends ServiceImpl<StudentDao, StudentEntity> implements StudentService {
+
+    private static final Logger log = LoggerFactory.getLogger(StudentServiceImpl.class);
+
+    @Override
+    public StudentEntity findStudentByStudentCode(Long orgId, String studentCode) {
+        QueryWrapper<StudentEntity> wrapper = new QueryWrapper<>();
+        if (orgId != null) {
+            wrapper.lambda().eq(StudentEntity::getOrgId, orgId);
+        }
+        wrapper.lambda().eq(StudentEntity::getStudentCode, studentCode);
+        return baseMapper.selectOne(wrapper);
+    }
+
+}

+ 12 - 0
src/main/java/com/qmth/exam/reserve/service/impl/UserServiceImpl.java

@@ -1,5 +1,6 @@
 package com.qmth.exam.reserve.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.exam.reserve.dao.UserDao;
 import com.qmth.exam.reserve.entity.UserEntity;
@@ -13,4 +14,15 @@ public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements
 
     private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);
 
+    @Override
+    public UserEntity findUserByLoginName(Long orgId, String loginName) {
+        QueryWrapper<UserEntity> wrapper = new QueryWrapper<>();
+        if (orgId != null) {
+            wrapper.lambda().eq(UserEntity::getOrgId, orgId);
+        }
+        wrapper.lambda().eq(UserEntity::getLoginName, loginName);
+        wrapper.lambda().eq(UserEntity::getEnable, true);
+        return baseMapper.selectOne(wrapper);
+    }
+
 }

+ 5 - 0
src/main/resources/mapper/StudentMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.qmth.exam.reserve.dao.StudentDao">
+
+</mapper>