本篇文章小编给大家分享一下spring-shiro权限控制realm代码实例,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看。
用户与角色实体
Role.java
@Data @Entity public class Role { @Id @GeneratedValue private Integer id; private Long userId; private String role; }
User.java
@Data @Entity public class User { @Id @GeneratedValue private Long id; private String username; private String password; }
Realm类
首先建立 Realm 类,继承自 AuthorizingRealm,自定义我们自己的授权和认证的方法。Realm 是可以访问特定于应用程序的安全性数据(如用户,角色和权限)的组件。
Realm.java
public class Realm extends AuthorizingRealm { @Autowired private UserService userService; //授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //从凭证中获得用户名 String username = (String) SecurityUtils.getSubject().getPrincipal(); //根据用户名查询用户对象 User user = userService.getUserByUserName(username); //查询用户拥有的角色 Listlist = roleService.findByUserId(user.getId()); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); for (Role role : list) { //赋予用户角色 info.addStringPermission(role.getRole()); } return info; } //认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //获得当前用户的用户名 String username = (String) authenticationToken.getPrincipal(); //从数据库中根据用户名查找用户 User user = userService.getUserByUserName(username); if (userService.getUserByUserName(username) == null) { throw new UnknownAccountException( "没有在本系统中找到对应的用户信息。"); } SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(),getName()); return info; } }
Shiro 配置类
ShiroConfig.java
@Configuration public class ShiroConfig { @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); MapfilterChainDefinitionMap = new LinkedHashMap (); //以下是过滤链,按顺序过滤,所以/**需要放最后 //开放的静态资源 filterChainDefinitionMap.put("/favicon.ico", "anon");//网站图标 filterChainDefinitionMap.put("/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } @Bean public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(myRealm()); return defaultWebSecurityManager; } @Bean public MyRealm myRealm() { MyRealm myRealm = new MyRealm(); return myRealm; } }
控制器
UserController.java
@Controller public class UserController { @Autowired private UserService userService; @GetMapping("/") public String index() { return "index"; } @GetMapping("/login") public String toLogin() { return "login"; } @GetMapping("/admin") public String admin() { return "admin"; } @PostMapping("/login") public String doLogin(String username, String password) { UsernamePasswordToken token = new UsernamePasswordToken(username, password); Subject subject = SecurityUtils.getSubject(); try { subject.login(token); } catch (Exception e) { e.printStackTrace(); } return "redirect:admin"; } @GetMapping("/home") public String home() { Subject subject = SecurityUtils.getSubject(); try { subject.checkPermission("admin"); } catch (UnauthorizedException exception) { System.out.println("没有足够的权限"); } return "home"; } @GetMapping("/logout") public String logout() { return "index"; } }
Service
UserService.java
@Service public class UserService { @Autowired private UserDao userDao; public User getUserByUserName(String username) { return userDao.findByUsername(username); } @RequiresRoles("admin") public void send() { System.out.println("我现在拥有角色admin,可以执行本条语句"); } }
shiro权限不生效原因分析
shiro遇到的坑
-项目中使用shiro做登录校验和权限管理,在配置权限时遇到小坑,记录一下。
环境:springboot+freemarker+shiro
场景:后台管理,配置菜单以及按钮权限,分为三个层级,一二级暂时只考虑是否查看权限,第三层级为页面按钮权限,分增删改查。详情看图
问题:一二层级正常,第三层级权限不起作用!
权限标签定义如下:
开始怀疑是数据库没有录入,查看后权限标签与角色已对应,排除。
后面怀疑是页面问题,后面把第三层级标签与第一二层级同一页面,依然不起作用,排除。
后面怀疑是权限标签定义问题,把第三层级标签改为one:page1:data:add,奇迹出现,权限生效。证实权限标签定义出了问题。
问题原因:权限标签定义问题
但是后来想想为什么会出现这种问题,每个标签都是独一无二的,对此我对shiro对于权限标签的校验产生了兴趣,查看源码,一路debug后最终在org.apache.shiro.authz.permission中看到了关键所在,核心代码如下
//当这个方法返回true时说明有此权限 //这个p是代表当前循环匹配到的权限标签 public boolean implies(Permission p) { // By default only supports comparisons with other WildcardPermissions if (!(p instanceof WildcardPermission)) { return false; } WildcardPermission wp = (WildcardPermission) p; //把当前标签转分割成一个set集合(如one:page1:view:add 会分割成[[one], [page1], [view], [add]]) List> otherParts = wp.getParts(); int i = 0; //循环匹配权限标签 for (Set otherPart : otherParts) { // If this permission has less parts than the other permission, everything after the number of parts contained // in this permission is automatically implied, so return true //当全部循环匹配完没有返回false,则返回true,这个getparts()方法是获取当前角色当前循环的权限标签([[one], [page1], [view]]) if (getParts().size() - 1 < i) { return true; } else { Set part = getParts().get(i); /*如果包含有‘*'而且不包含当前分割后的标签则返回false, *当用户可以查看页面,也就是说当前角色拥有one:page1:view标签 *这里【!part.contains(WILDCARD_TOKEN)】返回true,第二个【part.containsAll(otherPart)】one会跟当前标签匹**配one, *也就是说这里全部循环完返回的都是false,所以最后都没true,于是在上面返回了一个true。 if (!part.contains(WILDCARD_TOKEN) && !part.containsAll(otherPart)) { return false; } i++; } }
忍者必须死34399账号登录版 最新版v1.0.138v2.0.72
下载勇者秘境oppo版 安卓版v1.0.5
下载忍者必须死3一加版 最新版v1.0.138v2.0.72
下载绝世仙王官方正版 最新安卓版v1.0.49
下载Goat Simulator 3手机版 安卓版v1.0.8.2
Goat Simulator 3手机版是一个非常有趣的模拟游
Goat Simulator 3国际服 安卓版v1.0.8.2
Goat Simulator 3国际版是一个非常有趣的山羊模
烟花燃放模拟器中文版 2025最新版v1.0
烟花燃放模拟器是款仿真的烟花绽放模拟器类型单机小游戏,全方位
我的世界动漫世界 手机版v友y整合
我的世界动漫世界模组整合包是一款加入了动漫元素的素材整合包,
我的世界贝爷生存整合包 最新版v隔壁老王
我的世界MITE贝爷生存整合包是一款根据原版MC制作的魔改整