reglogin + interceptor

登陆注册

  • 核心思路就是你登陆注册,我判断是否合法,然后创建Ticket,下发Ticket;
@Controller
public class LoginController {

    private static final Logger logger = LoggerFactory.getLogger(LoginController.class);

    @Autowired
    UserService userService;

    /**
     * regLogin 注册和登陆的处理;默认会跳转到登录页面
     * 该页面可以登陆也可以注册
     *
     * @param model 通过model传递到view,view再通过input传递next值
     * @param next  指之前浏览的页面,登陆注册完就可以跳转过去
     * @return
     */
    @RequestMapping(path = {"/reglogin"}, method = {RequestMethod.GET})
    public String regLogin(Model model,
                           @RequestParam(value = "next", defaultValue = "") String next) {
        model.addAttribute("next", next);
        return "login";
    }

    /**
     * reg register的简写;
     * 主要功能就是看看用户能不能进行注册;
     * 通过map得到的ticket跳转响应的页面
     *
     * @param model      model
     * @param username   用户名
     * @param password   密码
     * @param next       下一个跳转的页面
     * @param rememberme 是否记住
     * @param response   响应
     * @return
     */
    @RequestMapping(path = {"/reg"}, method = RequestMethod.POST)
    public String reg(Model model,
                      @RequestParam("username") String username,
                      @RequestParam("password") String password,
                      @RequestParam(value = "next", defaultValue = "") String next,
                      @RequestParam(value = "rememberme", defaultValue = "false") boolean rememberme,
                      HttpServletResponse response) {
        try {
            Map<String, String> map = userService.register(username, password);
            return checkTicket(model, next, rememberme, response, map);

        } catch (Exception e) {
            logger.error("注册异常" + e.getMessage());
            return "login";
        }
    }

    /**
     * 登陆主要就是需要查看用户是不是合法的;
     * 通过userService返回的map,来获取ticket,
     * 然后做出相应跳转
     *
     * @param model
     * @param username
     * @param password
     * @param rememberme 是否记住,决定于是否下发cookie
     * @param next       登录后要跳转的页面
     * @param response   通过响应来下发cookie
     * @return
     */
    @RequestMapping(path = {"/login"}, method = RequestMethod.POST)
    public String login(Model model,
                        @RequestParam("username") String username,
                        @RequestParam("password") String password,
                        @RequestParam(value = "rememberme", defaultValue = "false") boolean rememberme,
                        @RequestParam(value = "next", defaultValue = "") String next,
                        HttpServletResponse response) {
        try {
            Map<String, String> map = userService.login(username, password);
            return checkTicket(model, next, rememberme, response, map);

        } catch (Exception e) {
            logger.error("注册异常" + e.getMessage());
            return "login";
        }

    }

    /**
     * 将ticket的status置为0,也就是说不能用了,
     * 这样用户就需要重新登陆了,因为本地的cookie值 已经失效;
     * 因为服务器表示你这ticket不能用啊;
     *
     * @param ticket
     * @return
     */
    @RequestMapping(path = {"/logout"}, method = RequestMethod.GET)
    public String logout(@CookieValue("ticket") String ticket) {
        userService.logout(ticket);
        return "redirect:/";
    }

    /**
     * 检验ticket,通过map得到ticket,如果map没有ticket
     * 说明这注册或者登陆不合法,返回map中的msg给view,显示错误信息;
     * 拿到ticket就下发cookie,默认是session,如果点击记住我,时间就是
     * 5天,然后进行跳转,如果有next就跳转next
     * @param model
     * @param next
     * @param rememberme
     * @param response
     * @param map
     * @return
     */
    private String checkTicket(Model model, @RequestParam(value = "next", defaultValue = "") String next, @RequestParam(value = "rememberme", defaultValue = "false") boolean rememberme, HttpServletResponse response, Map<String, String> map) {
        if (map.containsKey("ticket")) {
            Cookie cookie = new Cookie("ticket", map.get("ticket"));
            cookie.setPath("/");
            if (rememberme) {
                cookie.setMaxAge(3600 * 24 * 5);
            }
            response.addCookie(cookie);
            if (StringUtils.isNotBlank(next)) {
                return "redirect:" + next;
            }
            return "redirect:/";
        } else {
            model.addAttribute("msg", map.get("msg"));
            return "login";
        }
    }
}

Ticket

  • 把Ticket叫做T票也不是没有道理的;简单来说就是服务器会制造门票,然后下发给客户端,如果你丢了(cookie过期T票就没了),就不能访问了;服务器也可以主动的将门票设置为不合法,要求你重新登陆一遍

  • 因此存放在服务器里的ticket有一个过期时间,本地cookie也有一个过期时间;

  • 可以通过UUID来生成ticket;
/**
     * 判断注册是否合法的函数
     * 如果合法的话,就添加盐,盐+password通过md5算法增加保密性;
     * 将用户加入数据库,添加ticket(服务器),然后下发(客户端)
     * @param username
     * @param password
     * @return
     */
    public Map<String, String> register(String username, String password) {
        Map<String, String> map = new HashMap<>();
        if (StringUtils.isBlank(username)) {
            map.put("msg", "用户名不能为空");
        }
        if (StringUtils.isBlank(password)) {
            map.put("msg", "密码不能为空");
        }
        User user = userDAO.selectByName(username);
        if (user != null) {
            map.put("msg", "该用户已经被注册");
            return map;
        }
        user = new User();
        user.setName(username);
        user.setSalt(UUID.randomUUID().toString().substring(0, 5));
        user.setHeadUrl(String.format("http://images.nowcoder.com/head/%dt.png", new Random().nextInt(1000)));
        //md5 需要重看
        user.setPassword(WendaUtil.MD5(password + user.getSalt()));
        userDAO.addUser(user);

        String ticket = addLoginTicket(user.getId());
        map.put("ticket", ticket);
        return map;
    }

    /**
     * 验证的登陆是否合法,添加ticket,下发ticket
     * @param username
     * @param password
     * @return
     */
    public Map<String, String> login(String username, String password) {
        Map<String, String> map = new HashMap<>();
        if (StringUtils.isBlank(username)) {
            map.put("msg", "用户名不能为空");
        }
        if (StringUtils.isBlank(password)) {
            map.put("msg", "密码不能为空");
        }
        User user = userDAO.selectByName(username);
        if (user == null) {
            map.put("msg", "用户名不存在");
            return map;
        }
        if (!WendaUtil.MD5(password + user.getSalt()).equals(user.getPassword())) {
            map.put("msg", "用户密码错误");
            return map;
        }

        String ticket = addLoginTicket(user.getId());
        map.put("ticket", ticket);
        return map;
    }

    /**
     * 增加ticket,注意日期
     * @param userId
     * @return
     */
    public String addLoginTicket(int userId) {
        LoginTicket loginTicket = new LoginTicket();
        loginTicket.setUserId(userId);
        Date now = new Date();
        now.setTime(now.getTime() + 3600L * 24 * 1000 * 1000);
        loginTicket.setExpired(now);
        loginTicket.setStatus(0);
        loginTicket.setTicket(UUID.randomUUID().toString().replace("-", ""));
        loginTicketDao.addTicket(loginTicket);
        return loginTicket.getTicket();

    }


    /**
     * 将ticket的status置为1
     *
     * @param ticket
     */
    public void logout(String ticket) {
        loginTicketDao.updateStatus(ticket, 1);
    }

Interceptor

  • 拦截器需要注册
@Component
public class WendaWebConfiguration extends WebMvcConfigurerAdapter {
    @Autowired
    PassportInterceptor passportInterceptor;

    @Autowired
    LoginRequiredInterceptor loginRequiredInterceptor;

    /**
     * 添加拦截器,拦截器会按照顺序执行
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(passportInterceptor);
        registry.addInterceptor(loginRequiredInterceptor).addPathPatterns("/user/*");
        super.addInterceptors(registry);
    }
}
  • 拦截器针对request
@Component
public class PassportInterceptor implements HandlerInterceptor {
    @Autowired
    LoginTicketDao loginTicketDao;

    @Autowired
    UserDAO userDAO;

    @Autowired
    HostHolder hostHolder;
    //拦截器是针对request的,有多少次request,就经历多少次拦截器
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String ticket = null;
        if (request.getCookies() != null) {
            for (Cookie cookie : request.getCookies()) {
                if (cookie.getName().equals("ticket")) {
                    ticket = cookie.getValue();
                    break;
                }
            }
        }
        if (ticket != null) {
            LoginTicket loginTicket = loginTicketDao.selectByTicket(ticket);
            if (loginTicket == null || loginTicket.getExpired().before(new Date()) || loginTicket.getStatus() != 0) {
                return true;
            }
            User user = userDAO.selectById(loginTicket.getUserId());
            hostHolder.setUser(user);

        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        if (modelAndView != null) {
            modelAndView.addObject("user", hostHolder.getUser());
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        hostHolder.clear();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值