admin管理员组文章数量:1794759
Java实现登录功能(一)
Java实现登录功能(一)
文章目录
- Java实现登录功能(一)
- 前言
- 一、Token的认证流程及优点
- 二、JWT
- 三、Java基于JWT实现登录功能
-
- 1.引入pom依赖
- 2.编写JWT工具类
- 3.编写登录接口
- 4.Java后端校验Token测试
- 5.Vue登录页面中的存储Token方法
- 6.Vue前端每次请求资源携带Token方法
- 总结
前言
刚开始学习Java的时候,你是否有过疑问,登录功能就是简单地查询数据库对比一下账号密码就行了吗?在进行权限认证的时候,又该怎么办呢?每次都在提交的表单上加上账号密码吗?在这种情况下又该怎么防止CSRF(跨站请求伪造)呢 以下介绍一种现在流行的基于JWT的Token认证实现的登录功能。
一、Token的认证流程及优点
认证流程:
1.客户端发送带有用户名和密码参数的登录请求 2.服务端收到请求,验证用户名和密码 3.验证通过后,服务端签发Token并返回token给客户端 4.客户端收到Token后存储到Cookie或者Storage等中 5.客户端每次向服务端请求资源时需要在cookie或者header请求头中携带服务端签发的token 6.服务端收到请求后验证客户端请求携带的token,如果验证通过就向客户端返回请求数据
一般情况下,Token是被Header请求头所携带的。 有着以下优点:
1.支持跨域:Cookie是无法跨域的,而Token可以放在header请求头发送,所以支持跨域。 2.无状态:Token认证方式在服务端不需要像传统的Session认证方式那样去记录SessionId,因为Token本身包含了登录用户的信,可以减轻服务端的压力。 3.支持移动端、小程序:当客户端是非浏览器平台时,Cookie是不被支持的,此时采用在Header请求头携带Token的认证方式会显得简单 4.能避免CSRF失效:由于CSRF依赖于Cookie,所以由Header请求头携带Token的认证方式不会发生CSRF,所以能避免CSRF
说明
CSRF——跨站请求伪造。其原理是通过伪造成其它内容的请求地址,诱导用户触发请求。如果用户在登录状态下触发请求,将会自动携带Cookie访问服务端,服务端接收请求后检查到Cookie内部的用户信会认为是登录用户本人的操作。
二、JWTJWT(JSON Web Token)是一种比较主流的使用规范。其结构分别由Header标头、Payload有效负载、Signature签名算法三部分组成。
1.Header负责记录令牌类型、签名算法等。 such as: {"alg":"HS256","type","JWT"} 2.Payload负责声明一些标准以及携带一些用户信 {"userId":"1","username":"mayikt"} 标准声明: iss:JWT签发者 sub:JWT所面向的用户 aud:JWT的接收者 exp:JWT的过期时间,过期时间必须大于签发时间 nbf:JWT的生效时间 iat:JWT的签发时间 jti:JWT的唯一身份标识,避免重复 自定义的声明: 一些不敏感的用户信。 such as: {"iss":"CJJ","sub":"custom","exp":"1640000000","iat":"1632000000","jti":"156sad54a615a4d56ad15a6sd15s8924","userId":"1"} 3.Signature防止Token被篡改,加盐,确保安全性 三、Java基于JWT实现登录功能 1.引入pom依赖 <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.18.3</version> </dependency> 2.编写JWT工具类 import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTDecodeException; import com.auth0.jwt.interfaces.DecodedJWT; import com.example.demo.domain.User; import java.io.UnsupportedEncodingException; import java.util.Date; import java.util.HashMap; import java.util.Map; public class JWTUtil { //token有效时长 private static final long EXPIRE=30*60*1000L; //token的密钥 可自行定义 private static final String SECRET="jwt"; public static String createToken(User user) throws UnsupportedEncodingException { //token过期时间 Date date=new Date(System.currentTimeMillis()+EXPIRE); //jwt的header部分 Map<String ,Object>map=new HashMap<>(); map.put("alg","HS256"); map.put("typ","JWT"); //使用jwt的api生成token String token= JWT.create() .withHeader(map) .withClaim("username", user.getUsername())//私有声明 .withExpiresAt(date)//过期时间 .withIssuedAt(new Date())//签发时间 .sign(Algorithm.HMAC256(SECRET));//签名 return token; } /** * 校验token的有效性 * 1 token的header和payload是否没改过 * 2 没有过期 */ public static boolean verify(String token){ try { //解密 JWTVerifier verifier=JWT.require(Algorithm.HMAC256(SECRET)).build(); verifier.verify(token); return true; }catch (Exception e){ return false; } } //无需解密也可以获取token的信 public static String getUsername(String token){ try { DecodedJWT jwt = JWT.decode(token); return jwt.getClaim("username").asString(); } catch (JWTDecodeException e) { return null; } } } 3.编写登录接口domain、mapper、service层请自行编写,其中Result类是统一返回结果集类
import com.example.demo.domain.User; import com.example.demo.service.UserService; import com.example.demo.utils.JWTUtil; import com.example.demo.utils.Result; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.io.UnsupportedEncodingException; @RestController public class LoginController { @Autowired private UserService userService; @PostMapping("/login") public Result login(@RequestParam String username, @RequestParam String password) throws UnsupportedEncodingException { User user=userService.getUserByPass(username, password); if(user == null){ return Result.fail("用户名或密码错误"); } //登录成功则调用JWTUtil类的创建Token方法返回客户端 String token= JWTUtil.createToken(user); return Result.succ(200,"登陆成功",token); } } 4.Java后端校验Token测试 import com.example.demo.utils.Result; import com.example.demo.utils.JWTUtil; import javax.servlet.http.HttpServletRequest; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/user") public class UserController { @GetMapping("/test") public Result test(HttpServletRequest request){ String token=req.getHeader("Authorization"); if(token == null){ return Result.fail("尚未登录"); } //获取到token中的用户信 System.out.println(JWTUtil.getUsername(token)); //可自行编写获取用户信后的操作 //...... return Result.succ("test"); } }此处仅进行测试,后续博客将介绍安全框架搭配使用。
5.Vue登录页面中的存储Token方法 methods: { submitLogin() { this.$refs.loginForm.validate((valid) => { if (valid) { this.loading = true this.postRequest('/login', this.loginForm, 'form').then((resp) => { if (resp) { // 存储用户token const tokenStr = resp.obj.tokenHead + resp.obj.token window.sessionStorage.setItem('tokenStr', tokenStr) let path = this.$route.query.redirect this.$router.replace( path == '/' || path == undefined ? '/home' : path ) } }) } else { this.$message.error('你还有未填写的信') return false } }) }, }, 6.Vue前端每次请求资源携带Token方法 import axios from 'axios' // 请求拦截器 axios.interceptors.request.use(config => { if (window.sessionStorage.getItem('tokenStr')) { //请求携带自定义token config.headers['Authorization'] = window.sessionStorage.getItem('tokenStr'); } return config }, error => { console.log(error); })温馨提示: 遇到报错跨域问题可参考 解决跨域问题
总结
本文简单地介绍了基于JWT的Token认证方式实现的登录功能。
先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦
版权声明:本文标题:Java实现登录功能(一) 内容由林淑君副主任自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.xiehuijuan.com/baike/1686792963a103626.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论