赞
踩
支持跨域访问: Cookie是不允许垮域访问的,这一点对Token机制是不存在的,前提是传输的用户认证信息通
过HTTP头传输.
无状态(也称:服务端可扩展行):Token机制在服务端不需要存储session信息,因为Token 自身包含了所有登
录用户的信息,只需要在客户端的cookie或本地介质存储状态信息.
更适用CDN: 可以通过内容分发网络请求你服务端的所有资料(如:javascript,HTML,图片等),而你的服
务端只要提供API即可.
去耦: 不需要绑定到一个特定的身份验证方案。Token可以在任何地方生成,只要在你的API被调用的时候,你
可以进行Token生成调用即可.
更适用于移动应用: 当你的客户端是一个原生平台(iOS, Android,Windows 8等)时,Cookie是不被支持的
(你需要通过Cookie容器进行处理),这时采用Token认证机制就会简单得多。
CSRF:因为不再依赖于Cookie,所以你就不需要考虑对CSRF(跨站请求伪造)的防范。
性能: 一次网络往返时间(通过数据库查询session信息)总比做一次HMACSHA256计算 的Token验证和解析
要费时得多.
不需要为登录页面做特殊处理: 如果你使用Protractor 做功能测试的时候,不再需要为登录页面做特殊处理.
基于标准化:你的API可以采用标准化的 JSON Web Token (JWT). 这个标准已经存在多个后端库(.NET, Ruby,
Java,Python, PHP)和多家公司的支持(如:Firebase,Google, Microsoft)
(1)创建maven工程,引入依赖
- <dependency>
- <groupId>io.jsonwebtoken</groupId>
- <artifactId>jjwt</artifactId>
- <version>0.6.0</version>
- </dependency>
(2)使用工具类JwtUtils
- /**
- * @author: Mr.Yang
- * @create: 2020-02-13 21:19
- **/
- @Getter
- @Setter
- @ConfigurationProperties("jwt.config")
- public class JwtUtils {
- //签名私钥
- private String key;
- //签名失效时间
- private Long failureTime;
-
- /**
- * 设置认证token
- *
- * @param id 用户登录ID
- * @param subject 用户登录名
- * @param map 其他私有数据
- * @return
- */
- public String createJwt(String id, String subject, Map<String, Object> map) {
-
- //1、设置失效时间啊
- long now = System.currentTimeMillis(); //毫秒
- long exp = now + failureTime;
-
- //2、创建JwtBuilder
- JwtBuilder jwtBuilder = Jwts.builder().setId(id).setSubject(subject)
- .setIssuedAt(new Date())
- //设置签名防止篡改
- .signWith(SignatureAlgorithm.HS256, key);
-
- //3、根据map设置claims
- for (Map.Entry<String, Object> entry : map.entrySet()) {
- jwtBuilder.claim(entry.getKey(), entry.getValue());
- }
- jwtBuilder.setExpiration(new Date(exp));
-
- //4、创建token
- String token = jwtBuilder.compact();
- return token;
- }
-
- /**
- * 解析token
- *
- * @param token
- * @return
- */
- public Claims parseJwt(String token) {
- Claims claims = Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody();
- return claims;
- }
-
- }
注意:
@ConfigurationProperties("jwt.config")需要在配置文件中配置
(3)配置JwtUtils类
- /**
- * 配置jwt
- *
- * @return
- */
- @Bean
- public JwtUtils jwtUtils() {
- return new JwtUtils();
- }
(4)编写登录方法
1、编写DAO层
- /**
- * @author: Mr.Yang
- * @create: 2020-02-13 21:55
- **/
- @Repository
- public interface UserDAO {
-
- public User selectByMobileUser(String mobile);
-
- public User selectByIdUser(String id);
- }
2、编写xml写Sql
- <select id="selectByMobileUser" parameterType="string" resultMap="userMap">
- select *
- from bs_user
- where mobile = #{mobile}
- </select>
3、编写service层
- /**
- * 根据mobile查询用户
- *
- * @param mobile
- * @return
- */
- public User selectByMobile(String mobile) {
- return userDAO.selectByMobileUser(mobile);
- }
4、编写controller层
- /**
- * 用户登录
- * 1.通过service根据mobile查询用户
- * 2.比较password
- * 3.生成jwt信息
- *
- * @param loginMap
- * @return
- * @requestBody把请求数据封装(前端以json方式传)
- */
- @RequestMapping(value = "/login", method = RequestMethod.POST)
- public Result login(@RequestBody Map<String, String> loginMap) {
- String mobile = loginMap.get("mobile");
- String password = loginMap.get("password");
- User user = userService.selectByMobile(mobile);
- //登录失败
- if (user == null || !user.getPassword().equals(password)) {
- //既可以使用抛异常,也可使用直接返回错误码(推荐)
- return new Result(ResultCode.MOBILEORPASSWORDERROR);
- } else {
- //其他数据以map集合存放在token中
- Map<String, Object> dataMap = new HashMap<>();
- dataMap.put("companyId", user.getCompanyId());
- dataMap.put("companyName", user.getCompanyName());
- //生成token并存入数据返回
- String token = jwtUtils.createJwt(user.getId(), user.getUsername(), dataMap);
- return new Result(Result.SUCCESS(), token);
- }
- }
5、测试
data就是返回的token,里面存有用户ID,用户姓名及以map形式存入的数据(这里主要看前端需要什么就存什么)
(6)用户登录成功之后,获取用户信息
- /**
- * 用户登录成功之后,获取用户信息
- * 1.获取用户id
- * 2.根据用户id查询用户
- * 3.构建返回值对象
- * 4.响应
- *
- * @param request
- * @return
- * @throws Exception
- */
- @RequestMapping(value = "/profile", method = RequestMethod.POST)
- public Result profile(HttpServletRequest request) throws PendingException, Exception {
-
- /**
- * 从请求头信息中获取token数据
- * 1.获取请求头信息:名称=Authorization(前后端约定)
- * 2.替换Bearer+空格
- * 3.解析token
- * 4.获取clamis
- */
-
-
- //1.获取请求头信息:名称=Authorization(前后端约定)
- String authorization = request.getHeader("Authorization");
- if (StringUtils.isEmpty(authorization)) {
- // throw new PendingException(ResCode.UNAUTHENTICATED);
- //系统未捕捉到请求头信息
- throw new CommonException(ResultCode.UNAUTHENTICATED);
- }
- //2.替换Bearer+空格
- String token = authorization.replace("Bearer ", "");
-
- //3.解析token
- Claims claims = jwtUtils.parseJwt(token);
- //4.获取clamis
- String userId = claims.getId();
-
- // String userId = "U01";
- User user = userService.selectByIdUser(userId);
-
- /**此处只是为了获取token中的用户数据,所有只简单返回用户对象,
- * 工作则按实际要求多表查询需要数据(根据用户ID查询权限)
- */
-
- return new Result(ResultCode.SUCCESS, user);
- }
(7)测试
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。