SpringBoot集成shiro
数据库设计
- sh_user:用户表,一个用户可以有多个角色
- sh_role: 角色表,一个角色可以有多个资源
- sh_resource:资源表
- sh_user_role:用户角色中间表
- sh_role_resource:角色资源中间表
首先自定义realm抽象类并实现
- package com.itheima.shiro.core;
- import org.apache.shiro.authc.AuthenticationException;
- import org.apache.shiro.authc.AuthenticationInfo;
- import org.apache.shiro.authc.AuthenticationToken;
- import org.apache.shiro.authz.AuthorizationInfo;
- import org.apache.shiro.realm.AuthorizingRealm;
- import org.apache.shiro.subject.PrincipalCollection;
- import javax.annotation.PostConstruct;
- /**
- * @Description:自定义realm的抽象类
- */
- public abstract class ShiroDbRealm extends AuthorizingRealm {
- /**
- * @Description 认证方法
- * @param token token对象
- * @return 认证信息
- */
- @Override
- protected abstract AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException ;
- /**
- * @Description 授权方法
- * @param principals 令牌对象
- * @return 授权信息
- */
- @Override
- protected abstract AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals);
- /**
- * @Description 自定义密码比较器
- * @param
- * @return
- */
- @PostConstruct
- public abstract void initCredentialsMatcher();
- }
复制代码 实现这个抽象类
- package com.itheima.shiro.core.impl;
- import com.itheima.shiro.constant.SuperConstant;
- import com.itheima.shiro.core.ShiroDbRealm;
- import com.itheima.shiro.core.base.ShiroUser;
- import com.itheima.shiro.core.base.SimpleToken;
- import com.itheima.shiro.core.bridge.UserBridgeService;
- import com.itheima.shiro.pojo.User;
- import com.itheima.shiro.utils.BeanConv;
- import com.itheima.shiro.utils.EmptyUtil;
- import org.apache.shiro.authc.*;
- import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
- import org.apache.shiro.authz.AuthorizationInfo;
- import org.apache.shiro.subject.PrincipalCollection;
- import org.apache.shiro.util.ByteSource;
- import org.springframework.beans.factory.annotation.Autowired;
- /**
- * @Description:自定义realm的抽象类实现
- */
- public class ShiroDbRealmImpl extends ShiroDbRealm {
- @Autowired
- UserBridgeService userBridgeService;
- /**
- * @Description 认证方法
- * @param token token对象
- * @return 认证信息
- */
- @Override
- protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
- //token令牌信息,这里的SimpleToken继承了UsernamePasswordToken
- SimpleToken simpleToken = (SimpleToken) token;
- //根据登录名查询user对象
- User user = userBridgeService.findUserByLoginName(simpleToken.getUsername());
- if (EmptyUtil.isNullOrEmpty(user)){
- throw new UnknownAccountException("账号不存在!");
- }
- //构建认证令牌对象(将User对象转换成ShiroUser对象,ShiroUser类比Users实体类多了资源列表等属性)
- ShiroUser shiroUser = BeanConv.toBean(user, ShiroUser.class);
- // 根据用户id获取资源列表,并设置到shiroUser对象
- shiroUser.setResourceIds(userBridgeService.findResourcesIds(shiroUser.getId()));
- String slat = shiroUser.getSalt();
- String password = shiroUser.getPassWord();
- //构建认证信息对象:1、令牌对象 2、密文密码 3、加密因子 4、当前realm的名称
- return new SimpleAuthenticationInfo(shiroUser, password, ByteSource.Util.bytes(slat), getName());
- }
- /**
- * @Description 授权方法
- * @param principals 令牌对象
- * @return 授权信息
- */
- @Override
- protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
- // 获得令牌对象
- ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal();
- return userBridgeService.getAuthorizationInfo(shiroUser);
- }
- /**
- * @Description 自定义密码比较器
- * @param
- * @return
- */
- @Override
- public void initCredentialsMatcher() {
- //指定密码算法
- HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(SuperConstant.HASH_ALGORITHM);
- //指定迭代次数
- hashedCredentialsMatcher.setHashIterations(SuperConstant.HASH_INTERATIONS);
- //生效密码比较器
- setCredentialsMatcher(hashedCredentialsMatcher);
- }
- }
复制代码 SimpleToken类(说明)
- package com.itheima.shiro.core.base;
- import org.apache.shiro.authc.UsernamePasswordToken;
- /**
- * @Description 自定义tooken
- */
- public class SimpleToken extends UsernamePasswordToken {
-
- /** serialVersionUID */
- private static final long serialVersionUID = -4849823851197352099L;
- private String tokenType;
-
- private String quickPassword;
- /**
- * Constructor for SimpleToken
- * @param tokenType
- */
- public SimpleToken(String tokenType, String username,String password) {
- super(username,password);
- this.tokenType = tokenType;
- }
-
- public SimpleToken(String tokenType, String username,String password,String quickPassword) {
- super(username,password);
- this.tokenType = tokenType;
- this.quickPassword = quickPassword;
- }
- public String getTokenType() {
- return tokenType;
- }
- public void setTokenType(String tokenType) {
- this.tokenType = tokenType;
- }
- public String getQuickPassword() {
- return quickPassword;
- }
- public void setQuickPassword(String quickPassword) {
- this.quickPassword = quickPassword;
- }
-
-
- }
复制代码 userBridgeService接口(说明)
- package com.itheima.shiro.core.bridge;
- import com.itheima.shiro.core.base.ShiroUser;
- import com.itheima.shiro.pojo.User;
- import org.apache.shiro.authz.AuthorizationInfo;
- import java.util.List;
- /**
- * @Description:用户信息桥接(后期会做缓存)
- */
- public interface UserBridgeService {
- /**
- * @Description 查找用户信息
- * @param loginName 用户名称
- * @return user对象
- */
- User findUserByLoginName(String loginName);
- /**
- * @Description 查询资源ids
- * @param userId 用户id
- * @return 资源id集合
- */
- List<String> findResourcesIds(String userId);
- /**
- * @Description 鉴权方法
- * @param shiroUser 令牌对象
- * @return 鉴权信息
- */
- AuthorizationInfo getAuthorizationInfo(ShiroUser shiroUser);
- /**
- * @Description 查询用户对应角色标识list
- * @param userId 用户id
- * @return 角色标识集合
- */
- List<String> findRoleList(String userId);
- /**
- * @Description 查询用户对应资源标识list
- * @param userId 用户id
- * @return 资源标识集合
- */
- List<String> findResourcesList(String userId);
- }
复制代码 ShiroUser类(说明)
SuperConstant类(说明)
- package com.itheima.shiro.constant;
- /**
- *
- * @Description 静态变量
- */
- public class SuperConstant {
-
- /**
- * 常量是
- */
- public static final String YES = "YES";
- /**
- * 常量否
- */
- public static final String NO = "NO";
-
- /**
- * 匿名用户ID
- */
- public static final String ANON_ID = "-1";
-
- /**
- * 树形根节点父Id
- */
- public static final String ROOT_PARENT_ID = "-1";
-
- /**
- * 树形根节点Id
- */
- public static final String ROOT_ID = "1";
- /**
- * 匿名用户登录名
- */
- public static final String ANON_LOGIN_NAME = "ANONYMITY";
- /**
- * 匿名用户真实名
- */
- public static final String ANON_REAL_NAME = "匿名";
-
-
- /**
- * hash算法
- */
- public static final String HASH_ALGORITHM = "SHA-1";
-
- /**
- * 计算次数
- */
- public static final int HASH_INTERATIONS = 1024;
- }
复制代码 ShiroConfig配置
PropertiesUtil类(说明)
- package com.itheima.shiro.properties;
- import com.itheima.shiro.utils.EmptyUtil;
- import lombok.extern.log4j.Log4j2;
- /**
- * @Description 读取Properties的工具类
- */
- @Log4j2
- public class PropertiesUtil {
- public static LinkProperties propertiesShiro = new LinkProperties();
- /**
- * 读取properties配置文件信息
- */
- static {
- String sysName = System.getProperty("sys.name");
- if (EmptyUtil.isNullOrEmpty(sysName)) {
- sysName = "application.properties";
- } else {
- sysName += ".properties";
- }
- try {
- propertiesShiro.load(PropertiesUtil.class.getClassLoader()
- .getResourceAsStream("authentication.properties"));
- } catch (Exception e) {
- log.warn("资源路径中不存在authentication.properties权限文件,忽略读取!");
- }
- }
- /**
- * 根据key得到value的值
- */
- public static String getShiroValue(String key) {
- return propertiesShiro.getProperty(key);
- }
- }
复制代码 authentication.properties配置文件
- /static/**=anon
- #登录链接不拦截
- /login/**=anon
- #访问/resource/**需要有admin的角色
- /resource/**=roles[dev,SuperAdmin]
- #其他链接是需要登录的
- /**=authc ```
复制代码 说明:过滤器链由路径+过滤器组成,它是自上而下有序的,一个一个去匹配的。如果上面匹配失败,则不会匹配下面的内容。
自定义过滤器
- package com.itheima.shiro.core.filter;
- import org.apache.shiro.subject.Subject;
- import org.apache.shiro.util.CollectionUtils;
- import org.apache.shiro.web.filter.authz.AuthorizationFilter;
- import javax.servlet.ServletRequest;
- import javax.servlet.ServletResponse;
- import java.io.IOException;
- import java.util.Set;
- /**
- * @Description:角色or判断过滤器,只要当前用户包含传入的角色集合中的一个角色,就判断通过
- */
- public class RolesOrAuthorizationFilter extends AuthorizationFilter {
- //TODO - complete JavaDoc
- @SuppressWarnings({"unchecked"})
- public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
- Subject subject = getSubject(request, response);
- String[] rolesArray = (String[]) mappedValue;
- if (rolesArray == null || rolesArray.length == 0) {
- //no roles specified, so nothing to check - allow access.
- return true;
- }
- Set<String> roles = CollectionUtils.asSet(rolesArray);
- for (String role : roles) {
- boolean flag = subject.hasRole(role);
- if (flag){
- return flag;
- }
- }
- return false;
- }
- }
复制代码 加载自定义过滤器
在 ShiroConfig类中配置如下:- /**
- * @Description 加载自定义过滤器
- */
- private Map<String, Filter> filters(){
- Map<String,Filter> map = new HashMap<>();
- // 这里的key表示过滤器的名称
- map.put("roles-or", new RolesOrAuthorizationFilter());
- return map;
- }
- //shiro过滤器管理
- @Bean("shiroFilter")
- public ShiroFilterFactoryBean shiroFilterFactoryBean(){
- ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
- shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager());
- //过滤器,指定自定义的过滤器
- shiroFilterFactoryBean.setFilters(filters());
- //过滤器链
- shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap());
- //登录页面
- shiroFilterFactoryBean.setLoginUrl("/login");
- //未授权页面
- shiroFilterFactoryBean.setUnauthorizedUrl("/login");
- return shiroFilterFactoryBean;
- }
复制代码 测试自定义过滤器
在 authentication.properties配置文件中修改内容如下:- #访问/resource/**需要有SuperAdmin或者dev的角色
- /resource/**=roles-or[dev,SuperAdmin]
复制代码 注解方式鉴权
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |