发表于: 2019-11-12 22:43:40
2 923
一、今天完成的事
1.完成shiro授权
1.在shiroConfig中加入两行代码
//权限不足跳转的页面
shiroFilterFactoryBean.setUnauthorizedUrl("/noAuthc");
//设置权限拦截器,当权限为superManager才能访问后台
filterChainDefinitionMap.put("/student/backDesk","perms[user:superManager]");
2.在自定义Realm类中加入权限认证
/**
* 权限认证,即登录过后,每个身份不一定,对应的所能看的页面也不一样。
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("------执行授权逻辑----------");
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//可能存在多个权限控制,所以用list来接收
Set<String> stringSet = new HashSet<>();
//和config中的filterChainDefinitionMap.put("/student/backDesk","perms[user:superManager]");对应
stringSet.add("user:superManager");
simpleAuthorizationInfo.setStringPermissions(stringSet);
return simpleAuthorizationInfo;
}
3.在controller中加入权限不足跳转的页面url
运行之后的效果
如果权限一致可以访问后台
如果权限不足跳转到权限不足页面
4.加入数据库查询功能,形成动态的授权
首先创建五个表。
创建五个表是为了能够更好的模拟角色管理,每个用户可以对应多个角色,每个角色可以对应多个权限
表一:user表,存放用户信息
create table user (
``id bigint auto_increment,
``name varchar(100),
``password varchar(100),
``constraint pk_users primary key(id)
) charset=utf8 ENGINE=InnoDB;
表二:role表,存放角色
create table role (
``id bigint auto_increment,
``name varchar(100),
``constraint pk_roles primary key(id)
) charset=utf8 ENGINE=InnoDB;
表三:permission表,存放权限
create table permission (
``id bigint auto_increment,
``name varchar(100),
``constraint pk_permissions primary key(id)
) charset=utf8 ENGINE=InnoDB;
表四:user_role的id联表,用于用户和角色联表查询
create table user_role (
``uid bigint,
``rid bigint,
``constraint pk_users_roles primary key(uid, rid)
) charset=utf8 ENGINE=InnoDB;
表五:role_permission的id联表,用于角色和权限联表查询
create table role_permission (
``rid bigint,
``pid bigint,
``constraint pk_roles_permissions primary key(rid, pid)
) charset=utf8 ENGINE=InnoDB;
在程序中新加两个实体类Role,Permission
public class Role implements Serializable {
private long id;
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Role{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
public class Permission {
private long id;
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Permission{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
然后编写RoleAndPermissionMapper
@Mapper
public interface RoleAndPermissionMapper {
/**
* 获取密码
* @param name
* @return
*/
@Select("select password from user where name=#{name}")
String getPassword(String name);
/**
*联表查询用户对应的角色
* @param name
* @return
*/
@Select("select role.name from user \n" +
"LEFT JOIN user_role on `user`.id=user_role.uid\n" +
"LEFT JOIN role on role.id=user_role.rid\n" +
"where `user`.name=#{name}")
Set<String> listRoles(String name);
/**
* 联表查询用户对应的权限
* @param name
* @return
*/
@Select("select permission.name from user \n" +
"LEFT JOIN user_role on `user`.id=user_role.uid\n" +
"LEFT JOIN role on role.id=user_role.rid\n" +
"LEFT JOIN role_permission on role.id=role_permission.rid \n" +
"LEFT JOIN permission on permission.id=role_permission.pid \n" +
"where `user`.name=#{name}")
Set<String> listPermissions(String name);
@Insert("insert into user_role(uid,rid) values((select id from user_role where name=#{name}),rid=#{rid})")
boolean insert(String name,long id);
}
改编CustomRealm
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("------执行授权逻辑----------");
String username = (String) SecurityUtils.getSubject().getPrincipal();
log.info(username);
//查询数据库获取权限和角色
Set<String> permissions = roleAndPermissionService.listPermissions(username);
Set<String> roles = roleAndPermissionService.listRoles(username);
log.info(permissions);
log.info(roles);
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//设置到shiro中,让shiro来管理
simpleAuthorizationInfo.setStringPermissions(permissions);
simpleAuthorizationInfo.setRoles(roles);
return simpleAuthorizationInfo;
}
在shiroConfig中修改权限
filterChainDefinitionMap.put("/student/backDesk","authc,perms[/student/backDesk]");
所以只有权限为“/student/backDesk”才能访问到后台管理页面
运行后的效果
后台日志可以看到权限
前台可以看到正常进入
切换另一个账号
可以看到权限只有update,只能操作update,后台就不能进入
前台页面就会显示
5.加入密码加密功能
在shiroConfig中加入两段代码
/**
* 加入加密配置
* @return
*/
@Bean(name = "credentialsMatcher")
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
// 散列算法:这里使用MD5算法;
hashedCredentialsMatcher.setHashAlgorithmName("md5");
// 散列的次数,比如散列两次,相当于 md5(md5(""));
hashedCredentialsMatcher.setHashIterations(2);
// storedCredentialsHexEncoded默认是true,此时用的是密码加密用的是Hex编码;false时用Base64编码
hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
return hashedCredentialsMatcher;
}
/**
* 创建Realm以便调用
* @return
*/
@Bean
public CustomRealm customRealm() {
CustomRealm customRealm = new CustomRealm();
// 告诉realm,使用credentialsMatcher加密算法类来验证密文
customRealm.setCredentialsMatcher(hashedCredentialsMatcher());
customRealm.setCachingEnabled(false);
return customRealm;
}
在controller中加入登录验证
@RequestMapping("/register/0")
public String toAddUser(){
return "register";
}
@RequestMapping("/register/1")
public String addUser(User user){
String pwd = user.getPassword() ;
String username = user.getName();
String password = new SimpleHash("MD5", pwd,
ByteSource.Util.bytes(username + "salt"), 2).toHex();
user.setPassword(password);
userService.insert(user);
return "redirect/login";
}
修改CustomRealm
pwd = new SimpleHash("MD5", pwd,
ByteSource.Util.bytes(username + "salt"), 2).toHex();
log.info(pwd);
if (user == null) {
throw new AuthenticationException("用户名错误");
}else if(!user.getPassword().equals(pwd)){
log.info("执行了吗");
throw new AuthenticationException("密码错误");
}
log.info("还在运行?");
SimpleAuthenticationInfo a = new SimpleAuthenticationInfo(username, user.getPassword(),getName());
return a;
二、遇到的问题
登录验证的时候出现了问题,token验证不成功,报错没解决
三、收获
授权管理的时候需要一起查询角色和权限,学习了spl的联表查询和联表插入
联表插入
insert into user_role(uid,rid) values((select id from user where name='dada'),1);
联表查询
"select permission.name from user \n" +
"LEFT JOIN user_role on `user`.id=user_role.uid\n" +
"LEFT JOIN role on role.id=user_role.rid\n" +
"LEFT JOIN role_permission on role.id=role_permission.rid \n" +
"LEFT JOIN permission on permission.id=role_permission.pid \n" +
"where `user`.name=#{nme}"
四、明天的计划
先解决bug
评论