springboot+jwt+shiro+redis实现微信小程序oauth2.0登录

思路:
微信小程序获取用户授权后能获取到授权code,
前端调用登录接口传给后端code获取用户openid等信息。
登录接口:通过微信api调用getSessionInfo获取openid等基本信息,
获取成功后判断是否为新用户进行登录/新增用户后登录,
通过jwt生成token与refreshToken,将token与refreshToken存入redis中并设置有效期,然后将token与refreshToken返回给前端。
前端每次调用接口在请求头中传入token。
后端使用shiro自定义filter拦截请求,并解析token进行校验,若token校验失败或者过期则返回固定code给前端。
前端请求收到对应code后调用refreh_token接口传入refreshToken获取新的token。
refreh_token接口:接受到refrehToken参数后进行校验,若校验通过则生成新的token并存入redis;若校验失败或者refrehToken过期则返回失败信息,前端接收到失败的信息后重新调用登录接口进行登录。

以下具体代码:
@GetMapping(“login”)
@ApiOperation(“微信登录”)
public AjaxResult login(String code){

    try {
        WxMaJscode2SessionResult info = wxMaService.getUserService().getSessionInfo(code);
        //这里是通过jdk方式调用微信api
        ResultToken token = new ResultToken();
        User user= userService.queryByOpenId(info.getOpenid());
        if(user==null){
            //保存新用户
            user=new User ();
            user.setOpenId(info.getOpenid());
            user.insert(user);
        }
        token.setUserId(viViuser.getId());
        String userToken = getToken(viViuser);
        String refreshToken = getRefreshToken(viViuser);
        token.setToken(userToken);
        token.setRefresh_token(refreshToken);
        //存入token与refreshToken并设置过期时间,refresh_toke的过期时间至少为token的两倍以上,这里使用指定前缀+userid作为key,token作为value
      redisRepository.setExpire(ViConstants.PREFIX_VI_REDIS_USER_TOKEN+viViuser.getId(),userToken,3600*24);
        redisRepository.setExpire(ViConstants.PREFIX_VI_REDIS_USER_REFRESH_TOKEN+viViuser.getId(),refreshToken,3600*24*7);

        return AjaxResult.success(token);

    } catch (WxErrorException e) {
        e.printStackTrace();
        return AjaxResult.error(e.getError().getErrorMsg());
    }
}
   public String getToken(User user) {
        String token="";
        token= JWT.create().withAudience(String.valueOf(user.getId())).withIssuedAt(new Date())
                .sign(Algorithm.HMAC256(ViConstants.PREFIX_VI_TOKEN_SIGNuser.getOpenId()));
        return token;
    }
public String getRefreshToken(User user) {
    String token="";
    token= JWT.create().withAudience(String.valueOf(user.getId())).withIssuedAt(new Date())
            .sign(Algorithm.HMAC256(ViConstants.PREFIX_VI_REFRESH_TOKEN_SIGN+user.getOpenId()));
    return token;
}

JWTFilter:

public class JWTFilter extends BasicHttpAuthenticationFilter {

@Override
protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
    //生成shiro中的token并交给shiro进行登录验证,登录验证过程在userRealm进行重写
    AuthenticationToken token = this.createToke
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
可以的,我可以为您提供一个基于Spring Boot、JWTShiroRedis的例子。这个例子将演示如何使用这些技术实现用户认证和授权,并且将用户的状态存储在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、JWTShiroRedis的例子。您可以根据您的需求进行修改和扩展。希望对您有帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值