文章目录
1、md5两次加密
1.1、引入依赖
<!-- md5 依赖 -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
1.2、md5工具类
从前端到数据库进行两次md5加密
1、再前端代码中先将密码进行第一次md5加密,保证盐值、md5加密策略和后端一致。
2、将加密后的密码传到后端进行第二次盐值加密(从数据库中取出盐),加密后与数据库中保存的加密后的密码对比
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Component;
/**
* @Description:
* @Author: sgc
* @Date: 2022/11/20 14:15
*/
@Component
public class MD5Util {
private static final String SALT = "1a2b3c4d";
public static String md5(String src){
return DigestUtils.md5Hex(src);
}
//从前端到后端加密(第一次加密)这一步在前端已经处理
public static String inputPassToFormPass(String inputPass){
String src = "" + SALT.charAt(0) + SALT.charAt(2) + inputPass + SALT.charAt(5) + SALT.charAt(4);
return DigestUtils.md5Hex(src);
}
//从后端到数据库加密(第二次加密)
public static String formPassToDBPass(String formPass,String salt){
String src = "" + salt.charAt(0) + salt.charAt(2) + formPass + salt.charAt(5) + salt.charAt(4);
return DigestUtils.md5Hex(src);
}
//从前端到后端加密,后端再到数据库加密
public static String inputPassToDBPass(String inputPass,String salt){
String formPass = inputPassToFormPass(inputPass);
String dbPass = formPassToDBPass(formPass, salt);
return dbPass;
}
public static void main(String[] args) {
//d3b1294a61a07da9b49b6e22b2cbd7f9
System.out.println(inputPassToFormPass("123456"));
System.out.println(formPassToDBPass("d3b1294a61a07da9b49b6e22b2cbd7f9","1h3g54j65"));
System.out.println(inputPassToDBPass("123456","1h3g54j65"));
}
}
2、自定义参数注解
1、自定参数注解
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* @Description:
* @Author: sgc
* @Date: 2022/11/20 19:27
*/
@Documented
@Constraint(validatedBy = { IsMobileValidator.class })
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
public @interface IsMobile {
boolean required() default true;
String message() default "手机号格式错误";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
2、实现参数校验接口
import com.sgc.utils.ValidatorUtil;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/**
* @Description:
* @Author: sgc
* @Date: 2022/11/22 19:25
*/
@Component
public class IsMobileValidator implements ConstraintValidator<IsMobile,String> {
private boolean required = false;
@Override
public void initialize(IsMobile constraintAnnotation) {
required = constraintAnnotation.required();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if(required){
return ValidatorUtil.isMobile(value);
}else {
if(StringUtils.isEmpty(value)){
return true;
}else {
return ValidatorUtil.isMobile(value);
}
}
}
}
3、注解使用
3、自定义方法注解 todo
4、session与cookie保存登录信息
1、登录成功后生成一个cookie(uuid作为key)
2、将cookie与user用户信息存在session内
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sgc.dao.UserDao;
import com.sgc.entity.User;
import com.sgc.exception.GlobalException;
import com.sgc.service.UserService;
import com.sgc.utils.CookieUtil;
import com.sgc.utils.MD5Util;
import com.sgc.utils.UUIDUtil;
import com.sgc.vo.LoginVo;
import com.sgc.vo.RespBean;
import com.sgc.vo.RespBeanEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
/**
* <p>
* 服务实现类
* </p>
*
* @author sgc
* @since 2022-11-20
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {
@Autowired
private UserDao userDao;
@Override
public RespBean doLogin(LoginVo loginVo, HttpServletRequest request, HttpServletResponse response) {
User user = userDao.selectById(loginVo.getMobile());
if(!user.getPassword().equals(MD5Util.formPassToDBPass(loginVo.getPassword(),user.getSalt()))){
throw new GlobalException(RespBeanEnum.LOGIN_ERROR);
}
//生成cookie
String ticket = UUIDUtil.uuid();
request.getSession().setAttribute(ticket,user);
CookieUtil.setCookie(request,response,"userTicket",ticket);
return RespBean.success();
}
}
3、下次访问其他接口时根据cookie查询用户信息判断是否登录,未登录跳转至登录页
package com.sgc.controller;
import com.sgc.entity.User;
import com.sgc.service.UserService;
import com.sgc.vo.LoginVo;
import com.sgc.vo.RespBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
/**
* @Description:
* @Author: sgc
* @Date: 2022/11/20 17:24
*/
@Slf4j
@RequestMapping("/goods")
@Controller
public class GoodsController {
@Autowired
private UserService userService;
/**
* 功能描述: 跳转商品列表页
*/
@RequestMapping("/toList")
public String toList(HttpSession session, Model model, @CookieValue("userTicket") String ticket) {
if(StringUtils.isEmpty(ticket)){
return "login";
}
User user = (User)session.getAttribute(ticket);
if(null == ticket){
return "login";
}
model.addAttribute("user",user);
return "goodsList";
}
}
5、HandlerMethodArgumentResolver的使用
HandlerMethodArgumentResolver是参数处理器
1、自定义HandlerMethodArgumentResolver
import com.sgc.entity.User;
import com.sgc.service.UserService;
import com.sgc.utils.CookieUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Description:
* @Author: sgc
* @Date: 2022/12/3 21:35
*/
@Component
public class UserArgumentResolver implements HandlerMethodArgumentResolver {
@Autowired
private UserService userService;
@Override
public boolean supportsParameter(MethodParameter parameter) {
//获取参数类型
Class<?> clazz = parameter.getParameterType();
return clazz == User.class;
}
@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer,
NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
//上面的supportsParameter通过后 会执行下面的方法
HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
HttpServletResponse response = nativeWebRequest.getNativeResponse(HttpServletResponse.class);
String ticket = CookieUtil.getCookieValue(request, "userTicket");
if(StringUtils.isEmpty(ticket)){
return null;
}
return userService.getUserByCookie(ticket,request,response);
}
}
2、加入WebMvcConfigurer的addArgumentResolvers
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
/**
* @Description:
* @Author: sgc
* @Date: 2022/12/3 21:32
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private UserArgumentResolver userArgumentResolver;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(userArgumentResolver);
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/static/");
}
}
3、调用方法时会进入拦截器
6、约定大于配置
springboot默认配置static下面的静态资源可以直接访问,但是自定义WebMvcConfigurer后就会失效。解决方法;在自定义的WebMvcConfigurer中配置重新配置。延申默认配置失效的场景要考虑是否自定了某些配置。