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

一、引言

传统软件,架构单一,登录认证相对简单,基本都是通过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操作带来的瓶颈。

时间: 2024-08-07 04:30:28

项目总结之二——登录认证的相关文章

008-shiro与spring web项目整合【二】认证、授权、session管理

一.认证 1.添加凭证匹配器 添加凭证匹配器实现md5加密校验. 修改applicationContext-shiro.xml: <!-- realm --> <bean id="customRealm" class="com.lhx.ssm.shiro.CustomRealm"> <!-- 将凭证匹配器设置到realm中,realm按照凭证匹配器的要求进行散列 --> <property name="creden

Spring Security 自定义登录认证(二)

一.前言 本篇文章将讲述Spring Security自定义登录认证校验用户名.密码,自定义密码加密方式,以及在前后端分离的情况下认证失败或成功处理返回json格式数据 温馨小提示:Spring Security中有默认的密码加密方式以及登录用户认证校验,但小编这里选择自定义是为了方便以后业务扩展,比如系统默认带一个超级管理员,当认证时识别到是超级管理员账号登录访问时给它赋予最高权限,可以访问系统所有api接口,或在登录认证成功后存入token以便用户访问系统其它接口时通过token认证用户权限

SpringSecurity实现前后端分离项目的登录认证

一.文章简介 本文简要介绍了spring security的基本原理和实现,并基于springboot整合了spring security实现了基于数据库管理的用户的登录和登出,登录过程实现了验证码的校验功能. 二.spring security框架简介 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.主要包括:用户认证(Authentication)和用户授权(Authorization)两个部分.用户认证指的是验证某个用户能

基于数字证书的二次登录认证流程

简介: 使用数字证书用来做二次登录认证是一种已经广泛使用的,能够有效保护用户账户的手段,即用户如果开启了数字证书保护,登录到应用系统时,不仅需要输入用户的账户和口令,还需要有这张证书配合才能登录,因此,即便用户的账户被盗去,在没有数字证书的情况下一样无法登录系统. 1.用户申请新证书流程: 场景1:用户登录YS,开启数字证书登录功能和新建证书申请. 2.用户使用数字证书登录流程(假设用户已开启数字证书). 3.删除证书流程: 4.关闭证书认证功能流程:

JavaWeb--Servlet过滤器Filter和SpringMVC的HandlerInterceptor(Session和Cookie登录认证)

拦截一些请求进行处理,比如通过它来进行权限验证,或者是来判断用户是否登陆,日志记录,编码,或者限制时间点访问等等,是非常有必要的.所以就有了此篇文章啦. 文章结构:(1)Servlet过滤器Filter:(2)SpringMVC的HandlerInterceptor:(3)对比认知. 一.Servlet过滤器Filter: 此部分是从赵四大佬那里学来的,并补充自己的认知 (1)概念: 能够对Servlet容器的请求和响应对象进行检查和修改. Servlet过滤器本身并不产生请求和响应对象,它只能

springboot集成spring security实现restful风格的登录认证 附代码

一.文章简介 本文简要介绍了spring security的基本原理和实现,并基于springboot整合了spring security实现了基于数据库管理的用户的登录和登出,登录过程实现了验证码的校验功能. 完整代码地址:https://github.com/Dreamshf/spring-security.git 二.spring security框架简介 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.主要包括:用户认证

用户注册登录认证模块

在项目中创建新应用:Login,来实现注册.登录.认证功能. 一.注册接口 1.创建注册路由 首先在工程路由中添加login应用路由: from django.contrib import admin from django.urls import path, include, re_path from django.views.static import serve from LuffyCity import settings urlpatterns = [ path('admin/', ad

shiro实现APP、web统一登录认证和权限管理

先说下背景,项目包含一个管理系统(web)和门户网站(web),还有一个手机APP(包括Android和IOS),三个系统共用一个后端,在后端使用shiro进行登录认证和权限控制.好的,那么问题来了web和APP都可以用shiro认证吗?两者有什么区别?如果可以,解决方案是什么?看着大家焦急的小眼神,接下来挨个解决上面的问题. web和APP可以用shiro统一登录认证吗? 可以.假如web和APP都使用密码登录的话,那没的说肯定是可以的,因为对于shiro(在此不会介绍shiro详细知识,只介

3、VS2010+ASP.NET MVC4+EF4+JqueryEasyUI+Oracle项目开发之——用户登录

最近由于项目赶着上线,一直没时间接着写博客,今天终于空出了时间.声名:我不是专业美工,所以界面问题,希望大家不要拍砖.登录界面如下: 在ASP.NET MVC中,要新增一个功能,我们首先要添加一个控制器,AccountController.cs,添加方法:右键单击Controllers文件夹, /// <summary> /// 登录页面 /// </summary> /// <returns></returns> public ActionResult I