5.jeecg的登录及权限(jwt+shiro)

1.登录流程

controller
在这里插入图片描述
先验证验证码
然后验证用户是否有效
在这里插入图片描述
然后验证用户名和密码,通过的话会生成token
在这里插入图片描述
生成token
在这里插入图片描述
生成token之后存到返回结果中返回给前端 key为”token”,然后设置redis缓存过期时间,这个时间是token过期时间的2倍,用作续期token使用。具体方法在ShiroRealm这个类中。

JWTToken刷新生命周期 (实现: 用户在线操作不掉线功能)

  • 1、登录成功后将用户的JWT生成的Token作为k、v存储到cache缓存里面(这时候k、v值一样),缓存有效期设置为Jwt有效时间的2倍
  • 2、当该用户再次请求时,通过JWTFilter层层校验之后会进入到doGetAuthenticationInfo进行身份验证
  • 3、当该用户这次请求jwt生成的token值已经超时,但该token对应cache中的k还是存在,则表示该用户一直在操作只是JWT的token失效了,程序会给token对应的k映射的v值重新生成JWTToken并覆盖v值,该缓存生命周期重新计算
  • 4、当该用户这次请求jwt在生成的token值已经超时,并在cache中不存在对应的k,则表示该用户账户空闲超时,返回用户信息已失效,请重新登录。
  • 注意: 前端请求Header中设置Authorization保持不变,校验有效性以缓存中的token为准。
  • 用户过期时间 = Jwt有效时间 * 2。
  • 在这里插入图片描述
    Jwtutil的sign方法就是根据用户名生成token
    在这里插入图片描述

2.token续期流程

请求进来会进行登录认证
在这里插入图片描述
从token中获取用户信息,如果获取到了,且用户状态正常,就判断token是否过期了。
在这里插入图片描述
如果过期了就续期。在这里插入图片描述

  • 过期的话重新生成token,重新设置过期时间,这时前端传的token也不需要变,只改redis缓存内容即可,因为是根据token获取用户信息来验证,登录的用户没有变的话,从token中获取的信息也是相同的,即使token的部分内容不同。这样过期的时候 就又有了一个小时的有效时间 redis是两个小时。

3.shiro权限认证

在这里插入图片描述

1.ShiroConfig类

在这里插入图片描述

1.shiroFilter方法

在这里插入图片描述
在这里插入图片描述

2.securityManager

在这里插入图片描述

3.缓存相关的

在这里插入图片描述
在这里插入图片描述

2.ShiroRealm类

具体执行拦截的类

在这里插入图片描述

1.support

在这里插入图片描述
应该是重新定义的token,需要重写此方法吧。(盲猜)

2.doGetAuthenticationInfo

在这里插入图片描述

3.checkUserTokenIsEffect

在这里插入图片描述

4.jwtTokenRefresh

在这里插入图片描述

5.doGetAuthorizationInfo

在这里插入图片描述

3.JwtToken类

实现了shiro的AuthenticationToken接口。
在这里插入图片描述

4.JwtFilter类

拦截的源头,请求进来会先到这里,然后交给ShiroRealm处理
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

可以的,我可以为您提供一个基于Spring Boot、JWTShiro和Redis的例子。这个例子将演示如何使用这些技术实现用户认证和授权,并且将用户的状态存储在Redis中。 首先,您需要创建一个Spring Boot项目并添加所需的依赖。 在pom.xml文件中添加以下依赖: ``` <dependencies> <!-- Spring Boot --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Shiro --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-web-starter</artifactId> <version>1.7.1</version> </dependency> <!-- JWT --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> <!-- Redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> </dependencies> ``` 接下来,创建一个名为`JwtUtils`的JWT工具类,用于生成和验证JWT令牌。您可以参考以下代码: ```java import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.util.Date; @Component public class JwtUtils { @Value("${jwt.secret}") private String secret; @Value("${jwt.expiration}") private int expiration; @PostConstruct public void init() { secret = Base64.getEncoder().encodeToString(secret.getBytes()); } public String generateToken(String username) { Date now = new Date(); Date expiryDate = new Date(now.getTime() + expiration * 1000); return Jwts.builder() .setSubject(username) .setIssuedAt(now) .setExpiration(expiryDate) .signWith(SignatureAlgorithm.HS512, secret) .compact(); } public String getUsernameFromToken(String token) { Claims claims = Jwts.parser() .setSigningKey(secret) .parseClaimsJws(token) .getBody(); return claims.getSubject(); } public boolean validateToken(String token) { try { Jwts.parser().setSigningKey(secret).parseClaimsJws(token); return true; } catch (Exception e) { return false; } } } ``` 然后,创建一个名为`RedisUtils`的Redis工具类,用于操作Redis。您可以参考以下代码: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.util.concurrent.TimeUnit; @Component public class RedisUtils { @Autowired private RedisTemplate<String, Object> redisTemplate; public void set(String key, Object value, long expiration) { redisTemplate.opsForValue().set(key, value, expiration, TimeUnit.SECONDS); } public Object get(String key) { return redisTemplate.opsForValue().get(key); } public void delete(String key) { redisTemplate.delete(key); } public boolean hasKey(String key) { return redisTemplate.hasKey(key); } } ``` 接下来,创建一个名为`JwtRealm`的Shiro Realm,用于验证JWT令牌和授权。您可以参考以下代码: ```java import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; public class JwtRealm extends AuthorizingRealm { @Autowired private JwtUtils jwtUtils; @Autowired private RedisUtils redisUtils; @Override public boolean supports(AuthenticationToken token) { return token instanceof JwtToken; } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // TODO: 实现授权逻辑 } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { JwtToken jwtToken = (JwtToken) token; String username = jwtUtils.getUsernameFromToken(jwtToken.getToken()); if (username == null || !jwtUtils.validateToken(jwtToken.getToken())) { throw new AuthenticationException("无效的令牌"); } // TODO: 查询用户信息并返回认证信息 return new SimpleAuthenticationInfo(username, jwtToken.getToken(), getName()); } } ``` 最后,创建一个名为`JwtToken`的Shiro Token,用于封装JWT令牌。您可以参考以下代码: ```java import org.apache.shiro.authc.AuthenticationToken; public class JwtToken implements AuthenticationToken { private String token; public JwtToken(String token) { this.token = token; } @Override public Object getPrincipal() { return token; } @Override public Object getCredentials() { return token; } } ``` 以上是一个基于Spring Boot、JWTShiro和Redis的例子。您可以根据您的需求进行修改和扩展。希望对您有帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值