码迷,mamicode.com
首页 > 其他好文 > 详细

项目总结之二——登录认证

时间:2016-06-07 22:35:01      阅读:411      评论:0      收藏:0      [点我收藏+]

标签:互联网   cookie   登录认证   

一、引言


    传统软件,架构单一,登录认证相对简单,基本都是通过Session来实现的,即通过对所有进入的URI进行解析,并取得当前Session中的User信息。而互联网软件,架构复杂,需部署多台机器,session并不唯一,写session方式会存在各种问题,因此我们使用写cookie的方式来进行认证。

    在这次项目中,我们使用的是springMVC拦截器及登录注解认证,以token的方式进行登录认证。


二、登录认证过程

    

    1、用户输入用户名、密码进行登录。

    2、通过mvc访问后台login方法,比对数据库(或缓存)中的用户名及密码是否一致。

    3、若一致,则根据用户信息生成一个唯一的token(可使用用户的信息进行几次MD5+UID)。

    4、将生成的token放入用户的cookie中,返回给用户。

    5、当用户访问相关功能时,判断该action是否加了登录认证注解,若加了该注解则需要通过拦截器进行token验证,若cookie中的token与实时生成的token一致,则将currentUser放入request中,否则不放。

    6、在该action中获取currentUser的值,进行登录认证判断及相关参数的使用。


三、开发实例(核心代码)


    1、login.jsp

    

<form id="login_form" action="../account/login" method="POST">
   <ul
class="form">
       <li><input
type="text" placeholder="账号" name="uid" value="$!uid"/></li>
       <li><input
type="password" placeholder="密码" name="password" value="$!password"/></li>
       <li><a
href="#" class="btn" onclick="document.getElementById(‘login_form‘).submit();return false">登录</a></li>
   </ul>
   <div
class="login_failure">$!error</div>
</form>



    2、AuthRequired(登录认证注解)

    

@Inherited
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthRequired {
}

    3、AuthHandlerInterceptor(登录认证拦截器)

    

@Component("authHandlerInterceptor")
public class AuthHandlerInterceptor implements HandlerInterceptor {
   @Resource
   private UserService userService;

   @Override
   public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
       if (handler.getClass().isAssignableFrom(HandlerMethod.class)) {
           AuthRequired authRequired = ((HandlerMethod) handler).getMethodAnnotation(AuthRequired.class);
           if (authRequired == null) {
               return true;
           }
           //cookie里面获取token
           Cookie[] cookies = httpServletRequest.getCookies();
           String token = "";

           if (cookies != null) {
               for (Cookie cookie : cookies) {
                   if (cookie.getName().equals("token")) {
                       token = cookie.getValue();
                   }
               }
           }

           if (null != token && !"".equals(token) && token.contains("_")) {
               int id = Integer.parseInt(token.split("_")[0]);
               String code = "";

               User user = userService.getUser(id);
               if (null != user && user.getLock() == 0) {
                   code = userService.generateLoginToken(user);
               }

               if (code.equals(token)) {
                   httpServletRequest.setAttribute("currentUser", user);
               } else {
                   httpServletResponse.sendRedirect("/account/login");
                   return false;
               }
           } else {
               httpServletResponse.sendRedirect("/account/login");
               return false;
           }
       }

       return true;
   }

   @Override
   public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
       if (httpServletRequest.getAttribute("currentUser") != null && null != modelAndView) {
           modelAndView.addObject("current", httpServletRequest.getAttribute("currentUser"));
       }
   }

   @Override
   public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

   }
}

    4、Login action

    

@RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(String uid,
                   
String password,
                   
Model model,
                   
HttpServletResponse response)  {
   try {
       if (StringUtils.isBlank(uid)) {
           throw new RuntimeException("账号必填");
       
}
       if (StringUtils.isBlank(password) || password.length() < 6) {
           throw new RuntimeException("密码必填并且至少6位");
       
}

       User userByUId = userService.getUserByUId(uid);
       if
( userByUId == null) {
           throw new RuntimeException("账号不存在");
       
}
       userByUId = null;
       
User user = userService.login(uid, password);
       if
(user == null) {
           throw new RuntimeException("账号或者密码错误");
       
}

       String token = userService.generateLoginToken(user);
       
Cookie cookie = new Cookie("token", token);
       
cookie.setPath("/");
       
response.addCookie(cookie);

       return
"redirect:/user/main";
   
} catch (Exception e) {
       logger.error("error", e);
       
model.addAttribute("error", e.getMessage());
       
model.addAttribute("uid", uid);
       
model.addAttribute("password", password);
       return
"/account/login";
   
}
}

    5、需要登录才能操作的action,有@AuthRequired注解说明需要登录拦截,只有成功才能进行相关操作。


    @AuthRequired
   @RequestMapping(value = {"/main"}, method = {RequestMethod.GET})
   public String goMainVm(@Value("#{request.getAttribute(‘currentUser‘)}") User currentUser,Model model, HttpServletRequest request) throws BizException {
       try {
           if (null == currentUser || null == currentUser.getPhone()) {
               throw new RuntimeException("请登录后操作");
           }

           //登录后的操作****************
           
           
           return "/user/main";
       } catch (Exception e) {
           logger.error("error", e);
           model.addAttribute("error", e.getMessage());
           return "/account/login";
       }


   }
   

    6、配置文件

<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter" />
<mvc:interceptors>
   <bean class="com.happywork.interceptor.AuthHandlerInterceptor"/>
</mvc:interceptors>

至此,登录认证完全搞定。


四、性能问题


    有人会问,这么频繁的去读取数据库,是否会带来一定的性能问题,这里做个简要说明,这只是功能实现思路而已,当用户量上去后,直接从缓存中获取,无需频繁操作数据库,这样就解决了频繁的IO操作带来的瓶颈。

本文出自 “垚海” 博客,请务必保留此出处http://tl2011.blog.51cto.com/6006611/1787073

项目总结之二——登录认证

标签:互联网   cookie   登录认证   

原文地址:http://tl2011.blog.51cto.com/6006611/1787073

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!