1.场景还原
可能还有很多小伙伴对token概念朦朦胧胧,今天笔者以项目中的用户登录的token验证需求跟大家讲讲其中的来龙去脉,希望能够理清大伙的思路。
2.需求分析
这个需求可能早已是老生常谈,但我觉得它永远也不会过时
①谷歌浏览器:login.html---->index.html;
②然后复制index.html的地址在IE浏览器地址栏上,这时普遍网站都会使访问界面直接返回到login.html
只有登录了才可以继续浏览,保证了用户的信息安全性,这个需求就得用到token验证。
3.实现方案
①token生成方法
public classToken {
//随机数发生器
public staticStringgenetateToken(){
String token = System.currentTimeMillis()+"";//获得毫秒数加随机数
String tokenMd5="";
try{
MessageDigest md = MessageDigest.getInstance("md5");
byte[] md5 = md.digest(token.getBytes());
BASE64Encoder base =newBASE64Encoder();
tokenMd5 = base.encode(md5);
}catch(NoSuchAlgorithmException e) {
e.printStackTrace();
}
returntokenMd5;
}
public static voidmain(String args[]){
System.out.println(genetateToken());
}
}
②实现后台登录接口
@GetMapping(value="/login")publicMapgetLogin(String loginName,String password){ String zhangxing = Token.genetateToken();session.setAttribute(SESSION_TOKEN,zhangxing);booleanlogin =false;//储存tokenString pwd =loginService.getPassword(loginName);Map map =newHashMap();if(pwd.equals(password)){ login =true;} map.put("login",login);map.put("token",zhangxing);returnmap;}
其中,在实现登录的同时生成token,并将其缓存到session中
③实现对所有controller拦截
1>拦截类
public classLoginInterceptorextendsHandlerInterceptorAdapter {@Overridepublic booleanpreHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throwsException { 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 finalStringNO_MATCH_PATH=".*/(login).*";
逻辑为:
取出session中的用户token,如果token为空就进行拦截;反之放行
2>配置并注册工程的拦截类
@Configurationpublic classCustomWebMvcConfigurerAdapterextendsWebMvcConfigurerAdapter {@Overridepublic voidaddInterceptors(InterceptorRegistry registry) {//拦截所有的controllerregistry.addInterceptor(newLoginInterceptor()).addPathPatterns("/**");}}
一个注解就能够通知springboot工程,只要符合要求就可以进行拦截匹配
@Configuration
④编写实现前端跳转的controller
@Controller@CrossOriginpublic classPageController {@RequestMapping("/login")publicStringlogin(){return"hello";}@RequestMapping("/success")publicStringsuccess(){return"factManage";}}
return 出来的路径定位到templates中相应的html资源,注意,PageController的上面不要再带上@RequestMapping
⑤看看hello.html的前端代码
token用户名:
密 码:
登录functiongetlogin(){alert($("#username").val());alert($("#pwd").val());$.ajax({type:"get",url:"http://localhost:8089/user/login",data:{"loginName":$("#username").val(),"password":$("#pwd").val() },xhrFields:{withCredentials:true},beforeSend:function(XMLHttpRequest){ },//请求成功回调success:function(data,textStatus){alert("进来了");alert(data.login);alert(data.token);if(data.login){localStorage.setItem("token",data.token);window.location.href="success";} },complete:function(XMLHttpRequest,textStatus){ },error:function(){alert("请求网络失败!。。。。。。");} });}
只要登录成功了便请求sucess的controller接口
window.location.href="success";
对应的success接口实现
@RequestMapping("/success")publicStringsuccess(){return"factManage";}
效果图:
1>登录
2>成功跳转
3.换IE请求首页http://localhost:8089/success
token显然为空,直接跳到登录界面,这样需求也就实现了,好了,我是张星,欢迎加入博主技术交流群,群号:313145288
csdn博客链接:http://blog.csdn.net/zhangxing52077/article/details/73195565
网友评论