package com.goufn.permission.shiro.realm; import com.goufn.permission.exception.TokenTimeoutException; import com.goufn.permission.model.SysUser; import com.goufn.permission.jwt.JWTToken; import com.goufn.permission.jwt.JWTUtil; import com.goufn.permission.service.MenuService; import com.goufn.permission.service.RoleService; import com.goufn.permission.service.UserService; import com.goufn.permission.utils.PasswordUtil; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.authc.*; import org.apache.shiro.authc.credential.CredentialsMatcher; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; 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.apache.shiro.util.ByteSource; import org.springframework.beans.factory.annotation.Autowired; import java.util.Set; import java.util.stream.Collectors; public class MyShiroRealm extends AuthorizingRealm { @Autowired private RoleService roleService; @Autowired private MenuService menuService; @Autowired private UserService userService; @Override public boolean supports(AuthenticationToken token) { return token instanceof JWTToken; } /** * 对用户进行角色授权 * * @param principals 用户信息 * @return 返回用户授权信息 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); String username = JWTUtil.getUsername(principals.toString()); SysUser user = userService.findByName(username); Set<String> roles = roleService.findRoleByUserId(user.getId()); Set<String> permissions = menuService.findPermsByUserId(user.getId()); permissions = permissions.stream().filter(s -> s != null && !s.equals("")).collect(Collectors.toSet()); authorizationInfo.setRoles(roles); authorizationInfo.setStringPermissions(permissions); return authorizationInfo; } /** * 对用户进行认证 * * @param authenticationToken 用户凭证 * @return 返回用户的认证信息 * @throws AuthenticationException 用户认证异常信息 * Realm的认证方法,自动将token传入,比较token与数据库的数据是否匹配 * 验证逻辑是先根据用户名查询用户, * 如果查询到的话再将查询到的用户名和密码放到SimpleAuthenticationInfo对象中, * Shiro会自动根据用户输入的密码和查询到的密码进行匹配,如果匹配不上就会抛出异常, * 匹配上之后就会执行doGetAuthorizationInfo()进行相应的权限验证。 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { // 这里的 token是从 JWTFilter 的 executeLogin 方法传递过来的,已经经过了解密 String token = (String) authenticationToken.getCredentials(); String username = JWTUtil.getUsername(token); if (StringUtils.isBlank(username)) { throw new AuthenticationException("token校验不通过"); } // 通过用户名查询用户信息 SysUser user = userService.findByName(username); if(user == null){ throw new UnknownAccountException(); } if (!JWTUtil.verify(token, username, user.getPassword())) { throw new TokenTimeoutException("token校验不通过"); } //认证信息里存放账号密码, getName() 是当前Realm的继承方法,通常返回当前类名 :databaseRealm SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( token, token, getName() ); return authenticationInfo; } // @Override // public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) { // //HashedCredentialsMatcher是shiro提供的解析盐的实现类 // HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(); // matcher.setHashAlgorithmName(PasswordUtil.algorithmName); // matcher.setHashIterations(PasswordUtil.hashIterations); // super.setCredentialsMatcher(matcher); // } }