提交 e598b10d 编写于 作者: cxt104926's avatar cxt104926

完善登录注册

上级 0eb5196a
......@@ -15,10 +15,6 @@ public class ApiException extends RuntimeException {
@Setter
private String message;
@Getter
@Setter
private Object data;
public ApiException(ErrorVM e) {
this.code = e.getCode();
this.message = e.getMessage();
......@@ -27,9 +23,10 @@ public class ApiException extends RuntimeException {
/**
* 系统错误
*/
public static final ErrorVM VERIFICATION_CODE_FAIL = new ErrorVM(-50001, "获取验证码失败");
public static final ErrorVM VERIFICATION_CODE_FAIL = new ErrorVM(-50001, "获取验证码失败,请刷新页面");
public static final ErrorVM E_LOGIN_EXCEPTION = new ErrorVM(-50002, "账户异常");
public static final ErrorVM E_REGISTER_CREATE_FAILURE = new ErrorVM(-50003, "账号创建失败");
public static final ErrorVM E_SYSTEM_ERROR = new ErrorVM(-50004, "系统错误,请刷新重试");
/**
* 提示
......@@ -38,6 +35,7 @@ public class ApiException extends RuntimeException {
public static final ErrorVM E_LOGIN_UNKNOWN_CODE = new ErrorVM(-10002, "验证码错误");
public static final ErrorVM E_LOGIN_INCORRECT_CREDENTIAL = new ErrorVM(-10003, "账号或者密码错误");
public static final ErrorVM E_LOGIN_EXCESSIVE_ATTEMPTS = new ErrorVM(-10004, "错误次数过多");
public static final ErrorVM E_RESET_ACCOUNT_ERROR = new ErrorVM(-10005, "找不到重置的账号,请刷新页面重试");
public static final ErrorVM E_REGISTER_EXISTENCE_ACCOUNT = new ErrorVM(-10006, "注册账号已存在");
/**
......
......@@ -12,7 +12,6 @@ import java.io.Serializable;
* <p>
* 统一响应信息
*/
@Getter
@Setter
@ToString
......
......@@ -2,7 +2,12 @@ package com.stu.stusystem.common;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author: cxt
* @time: 2021/1/21
* <p>
* 错误响应信息模板
*/
@Data
@NoArgsConstructor
public class ErrorVM {
......
......@@ -24,7 +24,7 @@ public class ApplicationRunnerImpl implements ApplicationRunner {
public void run(ApplicationArguments args) throws Exception {
StuUser admin = stuMapper.selectOne(new StuUser("admin"));
if (admin == null) {
int insert = stuMapper.insert(new StuUser("INIT20200908", "20200908", "admin", "1zEd9KsK+pN1/yqGuW2JgcDDFng=", Jurisdiction.ADMIN));
int insert = stuMapper.insert(new StuUser("INIT20200908", "admin", "admin", "usZen62Aorxe0w4a0f8FRsCQggA=", Jurisdiction.ADMIN));
if (insert != 1) {
log.debug("数据库插入管理员信息失败!");
throw new Exception("数据库初始化失败!请联系管理员!");
......
......@@ -7,6 +7,8 @@ import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
......@@ -28,26 +30,31 @@ public class MyShiroConfig {
// 设置 SecurityManager 环境
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 未登录时候跳转链接
shiroFilterFactoryBean.setLoginUrl("/index");
// shiroFilterFactoryBean.setLoginUrl("/index");
// 登录成功后要跳转的链接
// shiroFilterFactoryBean.setSuccessUrl("/index");
// shiroFilterFactoryBean.setSuccessUrl("/index");
// 后台报错时候跳转页面
// shiroFilterFactoryBean.set
// 未授权界面
// shiroFilterFactoryBean.setUnauthorizedUrl("/403");
// shiroFilterFactoryBean.setUnauthorizedUrl("/403");
// 在未授权时候返回json数据
Map<String, Filter> filters = new HashMap<>();
ShiroAuthenticationFilter authenticationFilter = new ShiroAuthenticationFilter();
filters.put("authc", authenticationFilter);
shiroFilterFactoryBean.setFilters(filters);
// 拦截器
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
// 下面是配置不会被拦截的链接
filterChainDefinitionMap.put("/static/**", "anon");
filterChainDefinitionMap.put("/login", "anon");
filterChainDefinitionMap.put("/getVerify", "anon");
filterChainDefinitionMap.put("/register", "anon");
filterChainDefinitionMap.put("/favicon.ico", "anon");
filterChainDefinitionMap.put("/v2/api-docs/**", "anon");
......@@ -55,7 +62,7 @@ public class MyShiroConfig {
filterChainDefinitionMap.put("/swagger-resources/**", "anon");
filterChainDefinitionMap.put("/webjars/springfox-swagger-ui/**", "anon");
// 配置退出过滤器
filterChainDefinitionMap.put("/logout", "logout");
// filterChainDefinitionMap.put("/logout", "logout");
// filterChainDefinitionMap.put("/add", "perms[权限添加]");
filterChainDefinitionMap.put("/**", "authc");
......
......@@ -30,8 +30,8 @@ public class MyShiroRealm implements Realm {
@Override
public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String account = (String) token.getPrincipal(); // 得到用户名
String password = new Sha1Hash(new String((char[]) token.getCredentials()), "salt", 5).toBase64(); // 为验证密码,将密码加密
String account = (String) token.getPrincipal(); // 得到账号
String password = new Sha1Hash(new String((char[]) token.getCredentials()), account, 5).toBase64(); // 为验证密码,将密码加密
StuUser stuUser = stuMapper.selectOne(new StuUser().setAccount(account));
if (stuUser == null) {
throw new UnknownAccountException(); // 账号错误
......@@ -39,12 +39,7 @@ public class MyShiroRealm implements Realm {
if (!stuUser.getPassword().equals(password)) {
throw new IncorrectCredentialsException(); // 如果密码错误
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(stuUser, stuUser.getPassword(), getName());
// 当验证都通过后,把用户信息放在session里
Session session = SecurityUtils.getSubject().getSession();
session.setAttribute("userInfo", stuUser);
return authenticationInfo;
return new SimpleAuthenticationInfo(stuUser, stuUser.getPassword(), getName());
}
@Autowired
......
package com.stu.stusystem.config;
import com.alibaba.fastjson.JSONObject;
import com.stu.stusystem.common.ApiResult;
import org.apache.shiro.web.filter.authc.AuthenticationFilter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author: cxt
* @time: 2021/3/11
*/
public class ShiroAuthenticationFilter extends AuthenticationFilter {
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("application/json");
ApiResult<Object> error = ApiResult.error(401, "未登录或会话超时,请重新登录!");
httpServletResponse.getWriter().write(JSONObject.toJSON(error).toString());
return false;
}
// 判断是否是ajax请求
// private boolean isAjax(ServletRequest request) {
// String header = ((HttpServletRequest) request).getHeader("X-Requested-With");
// if ("XMLHttpRequest".equalsIgnoreCase(header)) {
// return Boolean.TRUE;
// }
// return Boolean.FALSE;
// }
}
......@@ -4,7 +4,9 @@ import com.stu.stusystem.common.ApiException;
import com.stu.stusystem.common.ApiResult;
import com.stu.stusystem.controller.dto.RegisterDTO;
import com.stu.stusystem.controller.dto.StuUserDTO;
import com.stu.stusystem.model.StuUser;
import com.stu.stusystem.service.LoginService;
import com.stu.stusystem.service.vo.LoginVO;
import com.stu.stusystem.util.ValidateCodeUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
......@@ -13,15 +15,11 @@ import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author cxt
* @date 2020/9/9
......@@ -39,44 +37,50 @@ public class LoginController {
return "/index";
}
/**
* 登出
*/
@GetMapping("/logout")
@ResponseBody
@ApiOperation("登出")
public void logout() {
public ApiResult<String> logout() {
StuUser principal = (StuUser) SecurityUtils.getSubject().getPrincipal();
Subject currentUser = SecurityUtils.getSubject();
currentUser.logout();
log.info("《账号:{}》登出成功", principal.getAccount());
return ApiResult.success("登出成功!");
}
/**
* 登录验证
*/
@PostMapping(value = "/login")
@ResponseBody
@ApiOperation("登录验证")
public ApiResult<String> login(@RequestBody StuUserDTO stu, HttpServletRequest request) {
public ApiResult<LoginVO> login(@RequestBody StuUserDTO stu, HttpServletRequest request) {
loginService.verification(stu.getVerification(), request);
loginService.verification(stu, request);
return ApiResult.success(200, "登录成功!");
LoginVO verification = loginService.verification(stu, request);
return ApiResult.success("登录成功!", verification);
}
/**
* 注册验证
*/
@PostMapping("/register")
@ResponseBody
@ApiOperation("注册验证")
public ApiResult<String> registers(@RequestBody RegisterDTO registerDTO) {
loginService.register(registerDTO);
return ApiResult.success(200, "注册成功!");
return ApiResult.success("注册成功!");
}
@ApiOperation("更新账号信息")
@ResponseBody
@PutMapping("/updateStu")
public ApiResult<String> updateStu(@RequestBody StuUser dto) {
loginService.updateStu(dto);
return ApiResult.success("用户{}信息更新成功!" + dto.getAccount());
}
@ApiOperation("重置密码")
@ResponseBody
@GetMapping("/resetPassword")
public ApiResult<String> resetPassword(@RequestParam("id") String id) {
String s = loginService.resetPassword(id);
return ApiResult.success(s);
}
/**
* 前端获取验证码图片
* <p>
* 后台验证的时候从session中获取
*/
@GetMapping(value = "/getVerify")
@ApiOperation("获取验证码")
public void getVerify(HttpServletRequest request, HttpServletResponse response) {
......
......@@ -15,8 +15,10 @@ import lombok.NoArgsConstructor;
public class StuUserDTO {
@ApiModelProperty("账号")
private String account;
@ApiModelProperty("密码")
private String password;
@ApiModelProperty("验证码")
private String verification;
}
......@@ -8,6 +8,7 @@ import com.stu.stusystem.mapper.UserLogMapper;
import com.stu.stusystem.model.StuUser;
import com.stu.stusystem.model.UserLog;
import com.stu.stusystem.model.em.Jurisdiction;
import com.stu.stusystem.service.vo.LoginVO;
import com.stu.stusystem.util.IPUtil;
import com.stu.stusystem.util.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
......@@ -33,18 +34,17 @@ import java.util.List;
@Service
public class LoginService {
private UserLogMapper userLogMapper;
private StuMapper stuMapper;
/**
* 登录验证
*/
public Boolean verification(StuUserDTO stu, HttpServletRequest request) {
boolean mg = false;
public LoginVO verification(StuUserDTO stu, HttpServletRequest request) {
UsernamePasswordToken token = new UsernamePasswordToken(stu.getAccount(), stu.getPassword(), stu.getVerification());
Subject currentUser = SecurityUtils.getSubject();
try {
currentUser.login(token);
mg = true;
userLogMapper.insert(new UserLog(UUIDUtil.generate(), stu.getAccount(), IPUtil.getIpAddr(request), new Date()));
log.info("《账号:" + stu.getAccount() + "》登录成功");
} catch (UnknownAccountException | IncorrectCredentialsException uae) {
......@@ -60,7 +60,9 @@ public class LoginService {
} catch (AuthenticationException ae) {
log.info("AuthenticationException");
}
return mg;
String authorization = (String) currentUser.getSession().getId();
StuUser user = (StuUser) SecurityUtils.getSubject().getPrincipal();
return new LoginVO(user.getAccount(), user.getName(), user.getClassName(), user.getPhone(), authorization);
}
/**
......@@ -72,6 +74,9 @@ public class LoginService {
}
HttpSession session = request.getSession();
String code = (String) session.getAttribute("RANDOMVALIDATECODEKEY");
if (code == null) {
throw new ApiException(ApiException.VERIFICATION_CODE_FAIL);
}
String c = code.toLowerCase();
String v = newCode.toLowerCase();
if (!v.equals(c)) {
......@@ -85,7 +90,8 @@ public class LoginService {
public void register(RegisterDTO registerDTO) {
List<StuUser> stuUsers = stuMapper.selectByExample(new Example.Builder(StuUser.class).where(WeekendSqls.<StuUser>custom().andEqualTo(StuUser::getAccount, registerDTO.getAccount())).build());
if (stuUsers.isEmpty()) {
String password = new Sha1Hash(registerDTO.getPassword(), "salt", 5).toBase64();
String password = new Sha1Hash(registerDTO.getPassword(), registerDTO.getAccount(), 5).toBase64();
// todo 创建人信息添加
int insert = stuMapper.insert(new StuUser(UUIDUtil.generate(), registerDTO.getName(), registerDTO.getAccount(), registerDTO.getClassName(), password, registerDTO.getPhone(), registerDTO.getIdCard(), Jurisdiction.STUDENT));
if (insert != 1) {
throw new ApiException(ApiException.E_REGISTER_CREATE_FAILURE);
......@@ -95,6 +101,39 @@ public class LoginService {
}
}
/**
* 更新账号信息
*/
public void updateStu(StuUser dto) {
String account = dto.getAccount();
dto.setAccount(null);
dto.setJurisdiction(null);
// todo 更新人信息添加
int i = this.stuMapper.updateByExampleSelective(dto, new Example.Builder(StuUser.class)
.where(WeekendSqls.<StuUser>custom().andEqualTo(StuUser::getAccount, account)).build());
if (i != 1) {
throw new ApiException(ApiException.E_SYSTEM_ERROR);
}
}
/**
* 密码重置
*/
public String resetPassword(String id) {
StuUser stuUser = this.stuMapper.selectByPrimaryKey(id);
if (stuUser == null) {
throw new ApiException(ApiException.E_RESET_ACCOUNT_ERROR);
}
String s = new Sha1Hash("1", stuUser.getAccount(), 5).toBase64();
stuUser.setPassword(s);
// todo 更新人信息添加
int i = this.stuMapper.updateByPrimaryKeySelective(stuUser);
if (i != 1) {
throw new ApiException(ApiException.E_SYSTEM_ERROR);
}
return "重置成功!新密码:1";
}
@Autowired
public void setUserLogMapper(UserLogMapper userLogMapper) {
this.userLogMapper = userLogMapper;
......
package com.stu.stusystem.service.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* @author: cxt
* @time: 2021/3/11
* 登录返回
*/
@Data
@AllArgsConstructor
public class LoginVO {
@ApiModelProperty("账号")
private String account;
@ApiModelProperty("用户名")
private String name;
@ApiModelProperty("班级")
private String className;
@ApiModelProperty("电话")
private String phone;
@ApiModelProperty("凭证")
private String authorization;
}
......@@ -14,7 +14,9 @@ public class UUIDUtil {
public static String generate() {
UUID uuid = UUID.randomUUID();
byte[] uuidArr = asByteArray(uuid);
String s = new BASE64Encoder().encode(uuidArr);
return s.replace("=", "").replace("/", "_").replace("+", "-");
}
......
......@@ -17,13 +17,13 @@ import java.util.Random;
public class ValidateCodeUtil {
public static final String RANDOMCODEKEY = "RANDOMVALIDATECODEKEY";//放到session中的key
//private String randString = "0123456789";//随机产生只有数字的字符串 private String
//private String randString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";//随机产生只有字母的字符串
private String randString = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZzxcvbnmlkjhgfdsaqwertyuiop";//随机产生数字与字母组合的字符串
private int width = 95;// 图片宽
private int height = 25;// 图片高
private int lineSize = 60;// 干扰线数量
private int stringNum = 4;// 随机产生字符数量
//private final String randString = "0123456789";//随机产生只有数字的字符串 private String
//private final String randString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";//随机产生只有字母的字符串
private final String randString = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZzxcvbnmlkjhgfdsaqwertyuiop";//随机产生数字与字母组合的字符串
private final int width = 95;// 图片宽
private final int height = 25;// 图片高
private final int lineSize = 60;// 干扰线数量
private final int stringNum = 4;// 随机产生字符数量
private Random random = new Random();
......@@ -82,7 +82,6 @@ public class ValidateCodeUtil {
} catch (Exception e) {
log.error("将内存中的图片通过流动形式输出到客户端失败", e);
}
}
/**
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册