package com.hu.zhcc.shiro.security; import java.util.List; import com.hu.zhcc.shiro.service.ResourceService; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.springframework.beans.factory.annotation.Autowired; import com.alibaba.fastjson.JSONObject; import com.hu.zhcc.shiro.utils.JwtUtils; import io.jsonwebtoken.Claims; import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.MalformedJwtException; import io.jsonwebtoken.SignatureException; import io.jsonwebtoken.UnsupportedJwtException; /** * 无状态Shiro Realm * * @author hulichao * @date 2018/3/15 */ public class JwtRealm extends AuthorizingRealm { @Autowired private ResourceService resourceService; @Autowired private JwtUtils jwtUtils; @Override public boolean supports(AuthenticationToken token) { //仅支持StatelessToken类型的Token return token instanceof JwtToken; } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { /********************************************* * RestfulPermissionFilter 过滤器说明: * Actions representing HTTP Method values (GET -> read, POST -> create, etc) * private static final String CREATE_ACTION = "create"; * private static final String READ_ACTION = "read"; * private static final String UPDATE_ACTION = "update"; * private static final String DELETE_ACTION = "delete"; *********************************************/ // 如果不为securityManager配置缓存管理器,该方法在每次鉴权前都会从数据库中查询权限数据。 // 分布式环境下,建议将权限保存在redis中,避免每次从数据库中加载。 //JSONObject json = JSONObject.parseObject(principals.toString()); Claims claims = jwtUtils.parseJWT(principals.toString()); JSONObject json = JSONObject.parseObject(claims.getSubject()); // 得到用户的权限code List<String> permissionCodeList = resourceService.listPermissionCodeByUserId(json.getIntValue("userId")); SimpleAuthorizationInfo simpleAuthorInfo = new SimpleAuthorizationInfo(); for (String permissionCode : permissionCodeList) { if (permissionCode != null && !permissionCode.trim().equals("")) { simpleAuthorInfo.addStringPermission(permissionCode); } // 如果要添加基于角色的鉴权,可调用simpleAuthorInfo.addRole("role_name")添加用户所属角色。 } return simpleAuthorInfo; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { JwtToken jwtToken = (JwtToken) token; String jwt = (String) jwtToken.getPrincipal(); try { Claims claims = jwtUtils.parseJWT(jwt); //验证host JSONObject json = JSONObject.parseObject(claims.getSubject()); if(!jwtToken.getHost().equals(json.getString("host"))) { throw new AuthenticationException("令牌来路非法"); } return new SimpleAuthenticationInfo(jwt, Boolean.TRUE, json.getString("username")); } catch (ExpiredJwtException e) { throw new AuthenticationException("令牌过期:" + e.getMessage()); } catch (UnsupportedJwtException e) { throw new AuthenticationException("令牌无效:" + e.getMessage()); } catch (MalformedJwtException e) { throw new AuthenticationException("令牌格式错误:" + e.getMessage()); } catch (SignatureException e) { throw new AuthenticationException("令牌签名无效:" + e.getMessage()); } catch (IllegalArgumentException e) { throw new AuthenticationException("令牌参数异常:" + e.getMessage()); } catch (Exception e) { throw new AuthenticationException("令牌错误:" + e.getMessage()); } } }