在realm中动态查询用户的权限&角色
@Controller
@Scope("prototype")
@Namespace("/")
@ParentPackage("struts-default")
@Results({ @Result(name = "login", location = "/login.jsp"),
@Result(name = "index", type = "redirect", location = "/index.jsp"),
@Result(name = "list", type = "redirect", location = "/pages/system/user.jsp"), })
public class UserAction extends BaseAction<User> { @Autowired
private UserService userService; // 接收验证码
private String checkCode; public void setCheckCode(String checkCode) {
this.checkCode = checkCode;
} /**
* @Description: 基于shiro实现登陆(认证)
* @return
* @throws Exception
*
*/
@Action("userAction_login")
public String login() throws Exception {
// if(StringUtils.isNotBlank(model.getUsername())&&
// StringUtils.isNoneBlank(model.getPassword())&&StringUtils.isNotBlank(checkCode)){
// //判断验证码
// String realCheckCode = (String)
// ServletActionContext.getRequest().getSession().getAttribute("key");
// if(checkCode.equals(realCheckCode)){
// 相等,开始通过shiro实现认证
// 通过工具类获取subject对象
Subject subject = SecurityUtils.getSubject(); // 当前“用户”,未认证状态
// 创建认证令牌; 封装页面提交用户名,密码
AuthenticationToken token = new UsernamePasswordToken(model.getUsername(), Md5Util.encode(model.getPassword()));
;
// logion方法调用安全管理器;
try {
subject.login(token);
} catch (Exception e) {
e.printStackTrace();
// 认证失败
return "login";
}
// 认证通过
// 从主角中获取用户信息,将用户的信息存Session中
User user = (User) subject.getPrincipal();
ServletActionContext.getRequest().getSession().setAttribute("loginUser", user);
return "index";
// }
// }else{
// return "login";
// }
// return super.execute();
} // 属性驱动接收页面提交角色id
private Integer[] roleIds; public void setRoleIds(Integer[] roleIds) {
this.roleIds = roleIds;
} // 保存用户,用户关联角色
@Action("userAction_save")
public String save() throws Exception {
userService.save(model, roleIds);
return "list";
} // 用户分页查询
@Action("userAction_pageQuery")
public String pageQuery() {
Pageable pageable = new PageRequest(page-1, rows);
Page<User> page = userService.findAll(pageable);
this.java2Json(page, new String[]{"roles"});
return null;
} }
/**
* @Description: 安全管理器最终调用realm,进行访问安全数据
*
* @Title: BosRealm.java
*/
public class BosRealm extends AuthorizingRealm{ @Autowired
private UserDao userDao; @Autowired
private PermissionDao permissionDao; @Autowired
private RoleDao roleDao;
/**
* @Description:
* @param token subject.login方法中传 用户名密码令牌
* @return
*/
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("开始认证");
UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
//页面输入的用户名
//根据用户名查询数据库中真实密码
String username = usernamePasswordToken.getUsername();
User user = userDao.findByUsername(username);
if(user==null){
//用户名输出错误
return null; //当此方法中返回null,shiro会抛出异常 :未知账户异常
}
//比对密码工作交给shiro框架
//p1:主角 p2:令牌/真实密码 p3:当前realm名称
AuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), this.getName());
return info;
} /* //授权
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("开始授权");
//TODO 后期改造查询数据库中对应的权限,角色
//返回简单授权信息:包含当前用户有的权限点;角色
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//添加用户权限
info.addStringPermission("standard_page");
info.addStringPermission("courier_delete");
//添加用户角色
info.addRole("admin");
return info;
}*/ //授权
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
List<Permission> permissionList = new ArrayList<>();
List<Role> roleList = new ArrayList<>();
System.out.println("开始授权");
//返回简单授权信息:包含当前用户有的权限点;角色
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//如果系统内置账户:管理员账户,有所有的权限以及角色
Subject subject = SecurityUtils.getSubject();
User user = (User) subject.getPrincipal();
if(user.getUsername().equals("admin")){
permissionList = permissionDao.findAll();
roleList = roleDao.findAll();
}else{
//根据用户ID进行查询
permissionList = permissionDao.findByUserId(user.getId());
roleList = roleDao.findByUserId(user.getId());
} //添加用户权限
for (Permission permission : permissionList) {
info.addStringPermission(permission.getKeyword());
}
//添加用户角色
for (Role role : roleList) {
info.addRole(role.getKeyword());
}
return info;
} }
public interface RoleDao extends JpaRepository<Role, Integer> { @Query("select r from Role r inner join r.users u where u.id=?")
List<Role> findByUserId(Integer userId); }
public interface PermissionDao extends JpaRepository<Permission, Integer> { /**
* select distinct p.*
from t_permission p
inner join t_role_permission rp on rp.c_permission_id = p.c_id
inner join t_role r on rp.c_role_id = r.c_id
inner join t_user_role ur on ur.c_role_id = r.c_id
inner join t_user u on ur.c_user_id = u.c_id
where u.c_id = 52;
*/
@Query("select distinct p from Permission p inner join p.roles r inner join r.users u where u.id = ?")
List<Permission> findByUserId(Integer userId); }
aaarticlea/png;base64,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" alt="" />
/**
* @description:后台用户
*/
@Entity
@Table(name = "T_USER")
public class User implements Serializable{ @Id
@GeneratedValue
@Column(name = "C_ID")
private Integer id; // 主键
@Column(name = "C_BIRTHDAY")
private Date birthday; // 生日
@Column(name = "C_GENDER")
private String gender; // 性别
@Column(name = "C_PASSWORD")
private String password; // 密码
@Column(name = "C_REMARK")
private String remark; // 备注
@Column(name = "C_STATION")
private String station; // 状态
@Column(name = "C_TELEPHONE")
private String telephone; // 联系电话
@Column(name = "C_USERNAME", unique = true)
private String username; // 登陆用户名
@Column(name = "C_NICKNAME")
private String nickname; // 真实姓名 @ManyToMany(fetch=FetchType.EAGER) //为了页面展示角色信息,设置立即加载
@JoinTable(name = "T_USER_ROLE", joinColumns = {
@JoinColumn(name = "C_USER_ID", referencedColumnName = "C_ID") }, inverseJoinColumns = {
@JoinColumn(name = "C_ROLE_ID", referencedColumnName = "C_ID") })
private Set<Role> roles = new HashSet<Role>(0); public String getRoleString(){
String roleStrings = "";
for (Role role : roles) {
roleStrings+=role.getName() + " ";
}
return roleStrings;
} public String getBirthdayString(){
if(birthday!=null){
return new SimpleDateFormat("yyyy-MM-dd").format(birthday);
}
return "暂无数据";
} ......
/**
* @description:角色
*/
@Entity
@Table(name = "T_ROLE")
public class Role implements Serializable {
@Id
@GeneratedValue
@Column(name = "C_ID")
private Integer id;
@Column(name = "C_NAME")
private String name; // 角色名称
@Column(name = "C_KEYWORD")
private String keyword; // 角色关键字,用于权限控制
@Column(name = "C_DESCRIPTION")
private String description; // 描述 @ManyToMany(mappedBy = "roles")
private Set<User> users = new HashSet<User>(0); @ManyToMany
@JoinTable(name = "T_ROLE_PERMISSION", joinColumns = {
@JoinColumn(name = "C_ROLE_ID", referencedColumnName = "C_ID") }, inverseJoinColumns = {
@JoinColumn(name = "C_PERMISSION_ID", referencedColumnName = "C_ID") })
private Set<Permission> permissions = new HashSet<Permission>(0); @ManyToMany
@JoinTable(name = "T_ROLE_MENU", joinColumns = {
@JoinColumn(name = "C_ROLE_ID", referencedColumnName = "C_ID") }, inverseJoinColumns = {
@JoinColumn(name = "C_MENU_ID", referencedColumnName = "C_ID") })
private Set<Menu> menus = new HashSet<Menu>(0); ......
/**
* @description:权限名称
*/
@Entity
@Table(name = "T_PERMISSION")
public class Permission implements Serializable{ @Id
@GeneratedValue
@Column(name = "C_ID")
private Integer id;
@Column(name = "C_NAME")
private String name; // 权限名称
@Column(name = "C_KEYWORD")
private String keyword; // 权限关键字,用于权限控制
@Column(name = "C_DESCRIPTION")
private String description; // 描述 @ManyToMany(mappedBy = "permissions")
private Set<Role> roles = new HashSet<Role>(0); ......
/**
* @description:菜单
*/
@Entity
@Table(name = "T_MENU")
public class Menu implements Serializable{
@Id
@GeneratedValue
@Column(name = "C_ID")
private Integer id;
@Column(name = "C_NAME")
private String name; // 菜单名称
@Column(name = "C_PAGE")
private String page; // 访问路径
@Column(name = "C_PRIORITY")
private Integer priority; // 优先级
@Column(name = "C_DESCRIPTION")
private String description; // 描述 @ManyToMany(mappedBy = "menus")
private Set<Role> roles = new HashSet<Role>(0); @OneToMany(mappedBy = "parentMenu", fetch=FetchType.EAGER) //EAGER立即加载集合
private Set<Menu> childrenMenus = new HashSet<Menu>(); //存放当前菜单下级菜单 @ManyToOne
@JoinColumn(name = "C_PID")
private Menu parentMenu; //当前菜单上级菜单;外键字段 /**
* combotree 展示文本内容
*/
public String getText(){
return name;
} /**
* @Description: 返回json数据中 包含children children:[]
* @return
*
*/
public Set<Menu> getChildren(){
return childrenMenus;
} /**
* 返回ztree数据,父节点数据的id
*
*/
public Integer getpId(){
if(parentMenu!=null){
return parentMenu.getId();
}
return 0;
} ......
在realm中动态查询用户的权限&角色的更多相关文章
- 项目一:第十三天 1、菜单数据管理 2、权限数据管理 3、角色数据管理 4、用户数据管理 5、在realm中动态查询用户权限,角色 6、Shiro中整合ehcache缓存权限数据
1 课程计划 菜单数据管理 权限数据管理 角色数据管理 用户数据管理 在realm中动态查询用户权限,角色 Shiro中整合ehcache缓存权限数据 2 菜单数据添加 2.1 使用c ...
- spring security中动态更新用户的权限
在程序的执行过程中,有时有这么一种需求,需要动态的更新某些角色的权限或某些人对应的权限,当前在线的用户拥有这个角色或拥有这个权限时,在不退出系统的情况下,需要动态的改变的他所拥有的权限. 需求:张三 ...
- 项目一:第十四天 1.在realm中动态授权 2.Shiro整合ehcache 缓存realm中授权信息 3.动态展示菜单数据 4.Quartz定时任务调度框架—Spring整合javamail发送邮件 5.基于poi实现分区导出
1 Shiro整合ehCache缓存授权信息 当需要进行权限校验时候:四种方式url拦截.注解.页面标签.代码级别,当需要验证权限会调用realm中的授权方法 Shiro框架内部整合好缓存管理器, ...
- 阶段5 3.微服务项目【学成在线】_day18 用户授权_09-动态查询用户的权限-认证服务查询用户权限
认证服务查询用户权限 如果权限为空就New一个对象出来. 因为如果为空的话 下面 forEach就会报空指针的异常 启动服务测试 重新登陆 看到userExt已经获取到了用户的权限 权限的字符串 复制 ...
- 阶段5 3.微服务项目【学成在线】_day18 用户授权_08-动态查询用户的权限-用户中心查询用户权限
3.3 用户中心查询用户权限 3.3.1 需求分析 认证服务请求用户中心查询用户信息,用户需要将用户基本信息和用户权限一同返回给认证服务. 本小节实现用户查询查询用户权限,并将用户权限信息添加到的用户 ...
- Kafka SASL/SCRAM+ACL实现动态创建用户及权限控制
kafka系列文章 第一章 linux单机安装kafka 第二章 kafka--集群安裝部署(自带zookeeper) 第三章 Kafka SASL/SCRAM+ACL实现动态创建用户及权限控制 Ka ...
- 在查询用户的权限的时候 使用左外连接 和 access数据库中左外连接
一般做视图最好是做成左外连接的.而其作用尤其在我们查询用户当前的权限时尤为明显,我们将 权限表即模块表放→角色权限表→角色表→用户角色表→用户表 就这样left outer join 连接起来,这样就 ...
- oracle查询用户的权限
DBA_* 描述的是数据库中的所有对象 ALL_* 描述的是当前用户有访问权限的所有对象 USER_* 描述的是当前用户所拥有的所有对象 查看所有用户: select * from dba_user ...
- 优化mybatis框架中的查询用户记录数的案例
通过对mybatis框架的中核心接口和类的分析,发现之前写的那个小demo是有问题的.现在对其进行部分优化. 如果存在多个功能的时候,势必会有很多重复的代码,如,创建sqlsession对象,关闭sq ...
随机推荐
- httpd Apache服务
TCP/IP协议 跨Internet的主机间通讯 在建立通信连接的每一端,进程间的传输要有两个标志: IP地址和端口号,合称为套接字地址 socket address 客户机套接字地址定义了一个唯一的 ...
- AcFun 的视频架构演化实践——阅读心得
视频的核心技术栈 AcFun 弹幕视频网(acfun.tv)是中国最早上线的弹幕视频网站,也是最具影响力的弹幕视频平台.“AcFun”原取意于“AnimeComic Fun”.自2007年6月6日成立 ...
- Memcache启动停止
启动Memcached root -P /var/run/memcached.pid 1)启动参数说明: -d 选项是启动一个守护进程, -l 是监听的服务器IP地址,默认为所有网卡. -p 是设置M ...
- Android Popwindow使用总结
Android Popwindow使用总结 转 https://www.jianshu.com/p/3812ff5ef272 1.基本使用方法 View view = getLayoutInflate ...
- 18 Flutter仿京东商城项目 商品详情顶部tab切换 顶部下拉菜单 底部浮动导航
ProductContent.dart import 'package:flutter/material.dart'; import '../services/ScreenAdaper.dart'; ...
- vim基础学习1---简单命令
1:vim abc:如果有abc文件,则打开,否则创建之后打开 2:输入"i",才可以输入东西 3:按Esc,它是底行模式,再敲":wq 回车" 保存退出. 4 ...
- 生产者-消费者问题与quene模块
生产者-消费者问题与quene模块 下面使用线程锁以及队列来模拟一个典型的案例:生产者-消费者模型.在这个场景下,商品或服务的生产者生产商品,然后将其放到类似队列的数据结构中,生产商品的时间是不确定的 ...
- MYSQL的MYSQLDUMP命令
1.用mysqldump对MySQL数据库进行数据备份与恢复 下面假设要备份tm这个数据库:Shell>mysqldump -uroot –p123456 tm > tm_050519.s ...
- 在linux下php挂接mysql.so扩展的方法
第一步:进入php源码中的"ext/mysql"目录下命令:cd 第二步:在当前目录下运行phpize 命令:/usr/local/php524/bin/phpize phpize ...
- css 边框和圆角
CSS3圆角 border-radius属性 一个最多指定四个border -*- radius复合属性,这个属性允许你为元素添加圆角边框 语法 border-radius:1-4 length|% ...