问答社区-显示登录信息(Interceptor)
拦截器使用
1.定义拦截器,实现HandlerInterceptor接口
2.配置拦截器,为它指定拦截、排除的路径
拦截器应用
1.在请求开始时查询登录用户
2.在本次请求中持有用户数据
3.在模板视图上显示用户数据
4.在请求结束时清理用户数据
定义拦截器LoginTicketInterceptor
@Component
public class LoginTicketInterceptor implements HandlerInterceptor {
@Autowired
private UserService userService;
@Autowired
private HostHolder hostHolder;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//这里是一个Cookie工具类,遍历cookie[],获取相应的value
String ticket = CookieUtil.getValue(request, "ticket");
if (ticket != null) {
//查询凭证
LoginTicket loginTicket = userService.selectTicket(ticket);
if (loginTicket != null && loginTicket.getStatus() == 0 && loginTicket.getExpired().after(new Date())) {
//根据凭证查询用户
User user = userService.findUserById(loginTicket.getUserId());
//在本次请求中持有用户,多线程状态下ThreadLocal每个用户单独持有一个线程
hostHolder.setUsers(user);
//构建用户认证的结果,并存入SecurityContext,便于Security进行授权
Authentication authentication = new UsernamePasswordAuthenticationToken(
user, user.getPassword(), userService.getAuthorities(user.getId()));
SecurityContextHolder.setContext(new SecurityContextImpl(authentication));
}
}
return true;
}
//在模板之前调用
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
User user = hostHolder.getUser();
if (user != null && modelAndView != null) {
modelAndView.addObject("loginUser", user);
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
hostHolder.clear();
SecurityContextHolder.clearContext();
}
}HostHolder
@Component
public class HostHolder {
private ThreadLocal<User> users = new ThreadLocal<>();
public void setUsers(User user) {
users.set(user);
}
public User getUser() {
return users.get();
}
public void clear(){
users.remove();
}
}在config中配置Interceptor
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private LoginTicketInterceptor loginTicketInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginTicketInterceptor)
.excludePathPatterns("/**/*.css","/**/*.js","/**/*.png","/**/*.jpg","/**/*.jpeg");
}
}
前台页面需要加入判断th:if="${loginUser!=null}",当用户没登陆的时候显示“登录”,登陆后隐藏按钮,并显示用户相关信息
<ul class="navbar-nav mr-auto">
<li class="nav-item ml-3 btn-group-vertical">
<a class="nav-link" th:href="@{/index}">首页</a>
</li>
<li class="nav-item ml-3 btn-group-vertical" th:if="${loginUser!=null}">
<a class="nav-link position-relative" th:href="@{/letter/list}">消息<span class="badge badge-danger" th:text="${allUnreadCount!=0?allUnreadCount:''}">12</span></a>
</li>
<li class="nav-item ml-3 btn-group-vertical" th:if="${loginUser==null}">
<a class="nav-link" th:href="@{/register}">注册</a>
</li>
<li class="nav-item ml-3 btn-group-vertical" th:if="${loginUser==null}">
<a class="nav-link" th:href="@{/login}">登录</a>
</li>
<li class="nav-item ml-3 btn-group-vertical dropdown" th:if="${loginUser!=null}">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<img th:src="${loginUser.headerUrl}" class="rounded-circle" style="width:30px;"/>
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item text-center" th:href="@{|/user/profile/${loginUser.id}|}">个人主页</a>
<a class="dropdown-item text-center" th:href="@{/user/setting}">账号设置</a>
<a class="dropdown-item text-center" th:href="@{/logout}">退出登录</a>
<div class="dropdown-divider"></div>
<span class="dropdown-item text-center text-secondary" th:utext="${loginUser.username}">nowcoder</span>
</div>
</li>
</ul>显示状态
未登录
登陆后
科大讯飞公司氛围 477人发布