当前位置:网站首页>2. Login - verification code function and saving login status
2. Login - verification code function and saving login status
2022-07-26 02:09:00 【A snicker】
In the login interface , It mainly realizes two functions , Refresh the verification code and remember my function 
Verification Code
Generate captcha
Use kaptcha Generate verification code , Import jar package , Write corresponding config Configuration class , And then in controller Generate verification code in . newly build cookie, stay cookie Put the verification code in uuid, take cookie As key Deposit in redis, hold text As value, Add expiration time on .
adopt response.addCookie(cookie) hold cookie Send to front end ,OutputStream os = response.getOutputStream(); ImageIO.write(image,“png”,os); Output the picture to the browser .
@GetMapping("/kaptcha")
public void getKaptcha(HttpServletResponse response){
// Generate verification code
String text = kaptchaProducer.createText();
BufferedImage image = kaptchaProducer.createImage(text);
// Verification code attribution
String kaptchaOwner = CommunityUtil.generateUUID();
Cookie cookie = new Cookie("kaptchaOwner", kaptchaOwner);
cookie.setMaxAge(60);
cookie.setPath(contextPath);
response.addCookie(cookie);
// Deposit in Redis
String redisKey = RedisKeyUtil.getKaptchaKey(kaptchaOwner);
redisTemplate.opsForValue().set(redisKey,text,60, TimeUnit.SECONDS);
// Output image to browser
try{
OutputStream os = response.getOutputStream();
ImageIO.write(image,"png",os);
} catch (IOException e) {
LOGGER.error(" Response verification code failed :" + e.getMessage());
}
}
Verification code
// @CookieValue("kaptchaOwner") String kaptchaOwner
String kaptcha = null;
// cookie Not empty , adopt redis Of key obtain value
if(StringUtils.isNoneBlank(kaptchaOwner)){
String redisKey = RedisKeyUtil.getKaptchaKey(kaptchaOwner);
kaptcha = (String) redisTemplate.opsForValue().get(redisKey);
}
// Verification code error, etc
if(StringUtils.isBlank(kaptcha) || StringUtils.isBlank(code) || !kaptcha.equalsIgnoreCase(code)){
model.addAttribute("codeMsg"," The verification code is incorrect !");
return "site/login";
}
Save login status
Timeout of login credentials in the default state 12 Hours , Remember the login credential timeout in status 100 God .
service layer :
// Generate login credentials
LoginTicket loginTicket = new LoginTicket();
loginTicket.setUserId(user.getId());
loginTicket.setTicket(CommunityUtil.generateUUID());
loginTicket.setStatus(0);
loginTicket.setExpired(new Date(System.currentTimeMillis() + expiredSeconds * 1000));
String redisKey = RedisKeyUtil.getTicketKey(loginTicket.getTicket());
// loginTicket Will be serialized as json
redisTemplate.opsForValue().set(redisKey, loginTicket);
map.put("ticket", loginTicket.getTicket());
return map;
controller layer :
// Do you remember me
int expiredSeconds = rememberme ? REMEMBER_EXPIRED_SECONDS : DEFAULT_EXPIRED_SECONDS;
Map<String, Object> map = userService.login(username, password, expiredSeconds);
String key = "ticket";
if(map.containsKey(key)){
// newly build cookie, To configure cookie
Cookie cookie = new Cookie("ticket", map.get("ticket").toString());
cookie.setPath(contextPath);
cookie.setMaxAge(expiredSeconds);
response.addCookie(cookie);
return "redirect:/";
} else{
// Return error message
model.addAttribute("usernameMsg",map.get("usernameMsg"));
model.addAttribute("passwordMsg",map.get("passwordMsg"));
return "site/login";
}
Automatic login implementation
First encapsulate two gadget classes
From you to cookie Get in the ticket Value , First package one cookieUtil:
public class CookieUtil {
public static String getValue(HttpServletRequest request, String name) {
if (request == null || name == null) {
throw new IllegalArgumentException(" The parameter is empty. !");
}
Cookie[] cookies = request.getCookies();
// Traverse cookie, Find the one we want
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals(name)) {
return cookie.getValue();
}
}
}
return null;
}
}
The browser processes multiple user requests at the same time , For each user user Objects need to be stored , have access to session, however session rely on servlet api, We want to use and take in the method , To solve this problem , We need to adopt a new method to store user information ——ThreadLocal.
ThreadLocal, seeing the name of a thing one thinks of its function , Is the local thread , But this name is easy to misunderstand , Because it actually means local variables of local threads , First we need to know , Each request corresponds to a thread , This ThreadLocal It is a variable in the process of using this thread , This variable is owned by its thread , Each thread does not affect each other .
We encapsulate a tool HostHolder, Used to hold user information , Instead of session object . There are mainly add query and delete methods , Make multi-user login conflict free .
@Component
public class HostHolder {
private ThreadLocal<User> users = new ThreadLocal<>();
public void setUser(User user) {
users.set(user);
}
public User getUser() {
return users.get();
}
public void clear() {
users.remove();
}
}
Rewrite first preHandler Method , Use the front package cookieUtil Tools get ticket, Find out the user , And use hostHolder Hold users .
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// from cookie Get vouchers from
String ticket = CookieUtil.getValue(request, "ticket");
if (ticket != null) {
// Query voucher
LoginTicket loginTicket = userService.findLoginTicket(ticket);
// Check whether the voucher is valid
if (loginTicket != null && loginTicket.getStatus() == 0 && loginTicket.getExpired().after(new Date())) {
// Query user according to voucher
User user = userService.findUserById(loginTicket.getUserId());
// Hold user... In this request
hostHolder.setUser(user);
// Build the results of user authentication , And deposit in SecurityContext, In order to Security To authorize
Authentication authentication =
new UsernamePasswordAuthenticationToken(
user, user.getPassword(), userService.getAuthorities(user.getId())
);
SecurityContextHolder.setContext(new SecurityContextImpl(authentication));
}
}
return true;
}
Display user data on the template view
Then rewrite postHandle Method , stay modelAndView Add up user.
@Override
public void postHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {
User user = hostHolder.getUser();
if (user != null && modelAndView != null) {
modelAndView.addObject("loginUser", user);
}
}
Clean up user data at the end of the request
@Override
public void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
hostHolder.clear();
}
边栏推荐
- TI AM335x工控模块网络跟文件系统NFS的实现
- (CVPR 2019) GSPN: Generative Shape Proposal Network for 3D Instance Segmentation in Point Cloud
- 我来图书馆小程序签到流程分析
- Ti am335x industrial control module uses the Debian system of beaglebone (BBB)
- G. Count the trains (thought set + two points)
- 1. Mx6ul core module serial WiFi test (VIII)
- Tenant issues.
- 1. Mx6ul core module uses serial can and buzzer test (XI)
- Qt程序美化之样式表的使用方法,Qt使用图片作为背景与控件透明化,Qt自定义按钮样式
- D. Permutation restoration (greedy + double pointer)
猜你喜欢

CD from grabbing the track to building a streaming media server -- a case study of "moon in the hometown of sleep"

Design and driver transplantation of matrix keyboard circuit of Ti am335x industrial control module

Niuke net question brushing training (I)

mysql 事务隔离级别

还在用==0 null equal 判断空值吗,对isEmpty 和 isBlank有多少了解呢

【2021】【论文笔记】6G技术愿景——OTFS调制技术
![[xxl-job] xxl-job learning](/img/2c/d3872983e4228a3ef52a9d1bef836e.png)
[xxl-job] xxl-job learning

I.MX6UL核心模块使用连载-触摸屏校准 (九)

Ti am335x industrial control module uses the Debian system of beaglebone (BBB)

A pluggable am335x industrial control module onboard WiFi module
随机推荐
D. Permutation restoration (greedy + double pointer)
Monitoring of debezium synchronization debezium
JS add random pixel noise background to the page
Remember a laravel problem script @php artist package:discover handling the post autoload dump event returned with
Republishing foundation and configuration
Dest0g3 520 orientation (under update)
Design and driver transplantation of matrix keyboard circuit of Ti am335x industrial control module
HTC手机官解、S-ON/S-OFF与超级CID的关系
I.MX6UL核心模块使用连载-Iot-6ULX核心模块简要介绍 (一)
i.MX6ULL SNVS电源域GPIO状态保持验证
Programming basic environment variable setting of in-house SOC
How to install opengauss manually (non om mode)
CD from grabbing the track to building a streaming media server -- a case study of "moon in the hometown of sleep"
一款可插拔的AM335X工控模块板载wifi模块
A MCU event driven C framework
Implementation of Ti am335x industrial control module network and file system nfs
C# 迭代器的实现
Navica tool imports remote MySQL into local MySQL database
一种MCU事件型驱动C框架
商业智能BI全解析,探寻BI本质与发展趋势