用户登录流程图:
在spring拦截器中进行鉴权操作:
控制器的拦截:
import com.mooc.house.common.model.User; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.net.URLEncoder; @Component //成为spring ben public class AuthActionInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception { User user= UserContext.getUser(); if(user==null){ //重定向到登录界面 String msg= URLEncoder.encode("请先登录","utf-8"); String target = URLEncoder.encode(request.getRequestURL().toString(),"utf-8"); if ("GET".equalsIgnoreCase(request.getMethod())) { response.sendRedirect("/accounts/signin?errorMsg=" + msg + "&target="+target); return false; }else { response.sendRedirect("/accounts/signin?errorMsg="+msg); return false; } } return false; } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { } }
import com.google.common.base.Joiner; import com.mooc.house.common.constants.CommonConstants; import com.mooc.house.common.model.User; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.util.Map; @Component //实现拦截器接口 public class AuthInterceptor implements HandlerInterceptor { @Override //在控制器执行之前拦截执行的 public boolean preHandle(HttpServletRequest request, HttpServletResponse httpServletResponse, Object o) throws Exception { Map<String,String[]> map=request.getParameterMap(); //获取所有的请求 map.forEach((k,v)->{ if (k.equals("errorMsg") || k.equals("successMsg") || k.equals("target")) { request.setAttribute(k, Joiner.on(",").join(v)); } }); String reqUri=request.getRequestURI(); if(reqUri.startsWith("/static")||reqUri.startsWith("/error")){ return true; } HttpSession session=request.getSession(true); //没有的话创建 User user=(User)session.getAttribute(CommonConstants.USER_ATTRIBUTE); if(user!=null){ UserContext.setUser(user); } return true; } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { UserContext.remove(); } }
获取删除得到用户信息:
public class UserContext { private static final ThreadLocal<User> USER_THREAD_LOCAL=new ThreadLocal<>(); public static void setUser(User user){ USER_THREAD_LOCAL.set(user); } public static void remove(){ USER_THREAD_LOCAL.remove(); } public static User getUser(){ return USER_THREAD_LOCAL.get(); } }
注册到请求接口:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class WebMvcConf extends WebMvcConfigurerAdapter { @Autowired private AuthActionInterceptor authActionInterceptor; @Autowired private AuthInterceptor authInterceptor; //管理拦截请求 @Override public void addInterceptors(InterceptorRegistry registry){ registry.addInterceptor(authInterceptor).excludePathPatterns("/static").addPathPatterns("/**"); registry .addInterceptor(authActionInterceptor).addPathPatterns("/house/toAdd") .addPathPatterns("/accounts/profile").addPathPatterns("/accounts/profileSubmit") .addPathPatterns("/house/bookmarked").addPathPatterns("/house/del") .addPathPatterns("/house/ownlist").addPathPatterns("/house/add") .addPathPatterns("/house/toAdd").addPathPatterns("/agency/agentMsg") .addPathPatterns("/comment/leaveComment").addPathPatterns("/comment/leaveBlogComment"); super.addInterceptors(registry); } }
拦截器编写配置步骤:
在配置中加入:
domain.name=127.0.0.1:8090 spring.mail.host=smtp.163.com spring.mail.username= spring.mail.password= spring.mail.properties.mail.smtp.outh=true spring.mail.properties.mail.smtp.starttls.enable=true spring.mail.properties.mail.smtp.starttls.required=true
发送邮件:
import java.util.List; import java.util.concurrent.TimeUnit; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import com.google.common.base.Objects; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.cache.RemovalListener; import com.google.common.cache.RemovalNotification; import com.mooc.house.biz.mapper.UserMapper; import com.mooc.house.common.model.User; @Service public class MailService { @Autowired private JavaMailSender mailSender; @Value("${spring.mail.username}") private String from; @Value("${domain.name}") private String domainName; @Autowired private UserMapper userMapper; private final Cache<String, String> registerCache = CacheBuilder.newBuilder().maximumSize(100).expireAfterAccess(15, TimeUnit.MINUTES) .removalListener(new RemovalListener<String, String>() { @Override public void onRemoval(RemovalNotification<String, String> notification) { String email = notification.getValue(); User user = new User(); user.setEmail(email); List<User> targetUser = userMapper.selectUsersByQuery(user); if (!targetUser.isEmpty() && Objects.equal(targetUser.get(0).getEnable(), 0)) { userMapper.delete(email);// 代码优化: 在删除前首先判断用户是否已经被激活,对于未激活的用户进行移除操作 } } }).build(); private final Cache<String, String> resetCache = CacheBuilder.newBuilder().maximumSize(100).expireAfterAccess(15, TimeUnit.MINUTES).build(); @Async public void sendMail(String title, String url, String email) { SimpleMailMessage message = new SimpleMailMessage(); message.setFrom(from); message.setSubject(title); message.setTo(email); message.setText(url); mailSender.send(message); } /** * 1.缓存key-email的关系 2.借助spring mail 发送邮件 3.借助异步框架进行异步操作 * * @param email */ @Async public void registerNotify(String email) { String randomKey = RandomStringUtils.randomAlphabetic(10); registerCache.put(randomKey, email); String url = "http://" + domainName + "/accounts/verify?key=" + randomKey; sendMail("房产平台激活邮件", url, email); } /** * 发送重置密码邮件 * * @param email */ @Async public void resetNotify(String email) { String randomKey = RandomStringUtils.randomAlphanumeric(10); resetCache.put(randomKey, email); String content = "http://" + domainName + "/accounts/reset?key=" + randomKey; sendMail("房产平台密码重置邮件", content, email); } public String getResetEmail(String key){ return resetCache.getIfPresent(key); } public void invalidateRestKey(String key){ resetCache.invalidate(key); } public boolean enable(String key) { String email = registerCache.getIfPresent(key); if (StringUtils.isBlank(email)) { return false; } User updateUser = new User(); updateUser.setEmail(email); updateUser.setEnable(1); userMapper.update(updateUser); registerCache.invalidate(key); return true; } }