SpringBoot+Mybatis+PostMan(五):token登陆认证过程一(token生成与认证)
Springboot+Mybatis+redis+postman项目实战总目录*
SpringBoot+Mybatis+PostMan(五):token登陆认证过程二(redis缓存引入)
SpringBoot+Mybatis+PostMan(六):token登陆认证过程三(redis封装与干掉原来session,避免用户重复登陆)
番外篇:SpringBoot 用户注册时经MD5加密存入数据库
第二篇章:用户角色权限访问控制
SpringBoot+Mybatis+PostMan(七):用户角色权限访问控制入门(数据模拟实现,不带数据库)
SpringBoot+Mybatis+PostMan(八):用户角色权限访问控制一(数据库用户角色表查询组合)
SpringBoot+Mybatis+PostMan(九):用户角色权限访问控制二(加入资源表和资源角色对应表)
SpringBoot+Mybatis+PostMan(十):用户角色权限访问控制三(禁用session、启用token并集成redis)
当我们访问某个网站时,我们首先只能进入到登陆页面,系统其他页面时访问不进去的,所以这里需要通过拦截器实现拦截功能,只能对外界暴露注册和登陆页面,其余页面一律拦截住。用户登陆时将信息传递到服务器端,服务器会查询此用户在服务器是否有session,如果没有,那么就将用户拦截在登陆页面,如果用户信息在服务器端时存在的,那么服务器端为其开辟一个session内存,并为其生成一个sessionID。
这里用到的知识有拦截器、token认证等等,接下来就进行token认证过程。
项目代码获取地址:https://github.com/yeyuting-1314/testdemo_insert_page_token.git
一、准备工作
1. 首先添加依赖,这里拦截需要用到JWT工具,需要我们手工导入
<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.4.0</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.47</version> </dependency>
2. 接下来实现token工具类,实现token生成、获取特定属性、获取请求,以及获取到token。
@Component public class TokenUtil { /* * 生成token * */ public String generateToken(User user){ Date start = new Date() ; long currentTime = System.currentTimeMillis() + 60*60*1000 ; //一小时的有效时间 Date end = new Date(currentTime) ; String token = "" ; token = JWT.create() .withAudience(Integer.toString(user.getId())) .withAudience(user.getUserName()) .withIssuedAt(start) .withExpiresAt(end) .sign(Algorithm.HMAC256(user.getPassword())); return token ; } /* * 获取指定token中某个属性值 * */ public static String get(String token , String key){ List<String> list = JWT.decode(token).getAudience() ; String userId = list.get(0) ; return userId ; } /* * 获取request * */ public static HttpServletRequest getRequest(){ ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); return requestAttributes == null ? null : requestAttributes.getRequest() ; } /* * 获取token * */ public String getToken(HttpServletRequest request) { Cookie[] cookies = request.getCookies() ; for(Cookie c : cookies){ if(c.getName() == "token"){ return c.getValue() ; } } return null ; } }
3. 自定义拦截器类,preHandle这个方法会业务层执行前先行执行,用于检查该请求是否带有token,如果有的话就放行,让其进行token认证,如果没有的话就拦截住,重定向到登陆页面(一般这种情况值我们要访问除了login和loginCheck两个页面的其他页面时,会被拦截住,重定向到登陆页面,后面会有演示)
//自定义拦截器类 public class AuthenticationInterceptor implements HandlerInterceptor { @Autowired TokenUtil tokenUtil ; @Override public boolean preHandle (HttpServletRequest request , HttpServletResponse response , Object o )throws Exception{ //检查请求中是否存在token , 如果不存在就直接跳转到登陆页面 String token = tokenUtil.getToken(request) ; if(StringUtil.isEmpty(token)){ System.out.println("不存在token"); response.sendRedirect("/login"); return false ; } return true ; } }
4. 拦截器实现,将需要拦截的页面进行相应拦截
@Configuration public class MVCConfig implements WebMvcConfigurer { @Bean public HandlerInterceptor authenticationInterceptor(){ return new AuthenticationInterceptor(); } /* * 静态资源映射 * */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry){ registry.addResourceHandler("/static/**") .addResourceLocations("classpath:/static/") ; } @Override public void addInterceptors (InterceptorRegistry registry){ registry.addInterceptor(authenticationInterceptor()) //表示拦截所有请求 .addPathPatterns("/*") //表示取消对特定路径的拦截 .excludePathPatterns("/login") .excludePathPatterns("/loginCheck"); //这里一定不要写成/**/*.js的形式,spring boot无法识别 //取消对static目录下静态资源的拦截 // .excludePathPatterns("/static/**") ; } }
二、 这样一来准备工作就做好了,接下来就是业务层的实现了。
1. controller层实现
@GetMapping("/login") public String test1(){ System.out.println(PropertiesUtil.class.getClassLoader(). getResource("").getPath()); return "登陆界面" ; } @PostMapping("/loginCheck") @ResponseBody public Result login(@RequestBody User user , HttpServletResponse response){ Result result = userService.loginCheck(user , response) ; return result ; }
2. service层
public Result loginCheck(User user , HttpServletResponse response);
public Result loginCheck(User user , HttpServletResponse response){ User user1 = userMapper.selectByName(user.getUserName()) ; if(user1 == null ){ //response.sendRedirect("/login"); return Results.failure("用户不存在,") ; } if(!user1.getPassword().equals(user.getPassword())){ return Results.failure("密码输入错误") ; } String token = tokenUtil.generateToken(user1) ; System.out.println("token:" + token); Cookie cookie = new Cookie("token" , token) ; // 设置cookie的作用域:为”/“时,以在webapp文件夹下的所有应用共享cookie cookie.setPath("/"); response.addCookie(cookie); System.out.println("cookie:"+cookie); return Results.success("登陆成功") ; }
这样一来,业务层代码逻辑也书写完毕,接下来利用postman实现前端模拟。
数据库内容如下:
1. 若访问除了login和loginCheck外的其他页面,会被拦截回到登陆页面。
2. 如果用户名正确密码错误:
3. 用户名不存在
4. 用户名密码均正确,成功登陆。
这样一来,token认证登陆这一功能就实现了。
至此,结束。