用户登录之token验证

1.场景还原

     可能还有很多小伙伴对token概念朦朦胧胧,今天笔者以项目中的用户登录的token验证需求跟大家讲讲其中的来龙去脉,希望能够理清大伙的思路。

2.需求分析

这个需求可能早已是老生常谈,但我觉得它永远也不会过时

①谷歌浏览器:login.html---->index.html;

②然后复制index.html的地址在IE浏览器地址栏上,这时普遍网站都会使访问界面直接返回到login.html

只有登录了才可以继续浏览,保证了用户的信息安全性,这个需求就得用到token验证。

3.实现方案

①token生成方法

/**
 * Created by zhangxing on 2017/6/12.
 */
public class Token {

    //随机数发生器
    public static String genetateToken(){
        String token = System.currentTimeMillis()+"";//获得毫秒数加随机数
        String tokenMd5="";
        try {
            MessageDigest md = MessageDigest.getInstance("md5");
            byte[] md5 = md.digest(token.getBytes());
            BASE64Encoder base = new BASE64Encoder();
            tokenMd5 = base.encode(md5);

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        return tokenMd5;
    }

    public static  void main(String args[]){
        System.out.println(genetateToken());
    }
}

②实现后台登录接口

@GetMapping(value = "/login")
public Map,Object> getLogin(String loginName,String password){
    String zhangxing = Token.genetateToken();
    session.setAttribute(SESSION_TOKEN,zhangxing);

    boolean login = false;
    //储存token
    String pwd = loginService.getPassword(loginName);
    Map,Object> map = new HashMap, Object>();
    if(pwd.equals(password)){
        login = true;
    }
    map.put("login",login);
    map.put("token",zhangxing);
    return map;
}
其中,在实现登录的同时生成token,并将其缓存到session中

③实现对所有controller拦截

1>拦截类

public class LoginInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String userToken = (String) request.getSession().getAttribute(SESSION_TOKEN);

        // 初始化拦截器,设置不拦截路径
        String noMatchPath= Constants.NO_MATCH_PATH;
        String path=request.getServletPath();

        System.out.println("资源请求路径:"+path);
        if(path.matches(noMatchPath)){
            // 授权路径,不拦截
            return  true;
        } else if(null == userToken || "".equals(userToken)) {
            // 找不到用户Token,重定位到登录
            response.sendRedirect(request.getContextPath() + "/login");
            return  false;
        } else {
            // 设置扩展
            return  true;
        }
    }

} 

继承HandlerInterceptorAdapter,重载preHandler()方法,其中的match()方法是对不进行拦截匹配的资源进行正则匹配,其资源样式为

public static final String  NO_MATCH_PATH=".*/(login).*";

逻辑为:

取出session中的用户token,如果token为空就进行拦截;反之放行

2>配置并注册工程的拦截类

@Configuration
public class CustomWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //拦截所有的controller
        registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**");
    }
}

一个注解就能够通知springboot工程,只要符合要求就可以进行拦截匹配

@Configuration

④编写实现前端跳转的controller

@Controller
@CrossOrigin
public class PageController {

    @RequestMapping("/login")
    public String login(){
        return "hello";
    }

    @RequestMapping("/success")
    public String success(){
        return "factManage";
    }

}

return 出来的路径定位到templates中相应的html资源,注意,PageController的上面不要再带上@RequestMapping

⑤看看hello.html的前端代码

html>


    charset="utf-8">
    </span>token<span style="color:#e8bf6a;">
    
    

 
用户名:type="text" id="username">

密 码:type="text" id="pwd">

只要登录成功了便请求sucess的controller接口

 window.location.href ="success";
对应的success接口实现

@RequestMapping("/success")
public String success(){
    return "factManage";
}

效果图:

1>登录

用户登录之token验证_第1张图片

2>成功跳转

用户登录之token验证_第2张图片

3.换IE请求首页http://localhost:8089/success

用户登录之token验证_第3张图片

token显然为空,直接跳到登录界面,这样需求也就实现了,好了,我是张星,欢迎加入博主技术交流群,群号:313145288




你可能感兴趣的:(java,issue)