昨天去学了shiro的授权,没有添加太多功能
@RequiresAuthentication
验证用户是否登录,等同于方法subject.isAuthenticated()
@RequiresUser
验证用户是否被记忆,user有两种含义:
一种是成功登录的(subject.isAuthenticated() 结果为true);
另外一种是被记忆的(subject.isRemembered()结果为true)。
@RequiresGuest
验证是否是一个guest的请求,与@RequiresUser完全相反。
换言之,RequiresUser == !RequiresGuest。
此时subject.getPrincipal() 结果为null.
@RequiresRoles
例如:@RequiresRoles("aRoleName");
void someMethod();
如果subject中有aRoleName角色才可以访问方法someMethod。如果没有这个权限则会抛出异常AuthorizationException。
@RequiresPermissions
例如: @RequiresPermissions({"file:read", "write:aFile.txt"} )
void someMethod();
配置在Shiroconfig中
/**
* 下面两个Bean用于开启shiro aop注解支持.
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
@Bean
@ConditionalOnMissingBean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
return defaultAdvisorAutoProxyCreator;
}
@RequiresPermissions("adminUser:update")
@RequestMapping("/updateAdminUser")
public ResultObj updateAdminUser(@RequestBody AdminUser user){
return adminUserService.updateAdminUser(user);
}
像这样子添加
//用户授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
log.info("开始用户授权");
String accessToken = (String) principalCollection.getPrimaryPrincipal();
Integer id = Integer.valueOf(JwtUtils.getUserId(accessToken));
//创建返回的info
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//先去redis里找,找不到再去claims里找
//以上留空为redis做准备
Claims claims = JwtUtils.getClaimsFromToken(accessToken);
List permissions = (List) claims.get(Constant.JWT_PERMISSIONS_KEY);
if(permissions != null){
info.addStringPermissions(permissions);
}
return info;
}
在用户第一次登录获得token的时候吧权限封装进token里
@Override
public ResultObj login(String username, String password) {
AdminUser user = adminUserDao.login(username);
int user_id = user.getId();
String user_password = user.getPassword();
//检查密码是否正确
boolean passwordFlag = PasswordUtils.matches(user.getSalt(), password, user_password);
if (user_id == 0 || !passwordFlag) {
return new ResultObj(Constant.ERROR, Constant.USERNAME_PASSWORD_ERROR, null);
}
if (!user.getAvailable()) {
return new ResultObj(Constant.ERROR, Constant.ADMINUSER_NOT_AVAILABLE, null);
}
//到这里就算登录通过,生成accessToken
Map claims = new HashMap<>();
//这里要加权限信息 加载claim中
//留空
//获取该用户所有角色
List roles = adminRoleDao.getAllRolesByUserId(user_id);
//用Set来去重用户所有权限
Set permissions = new HashSet<>();
for(AdminRole role : roles){
//查询用户所拥有的每个角色所拥有的权限
List permissionList = adminPermissionDao.getAllPermissionsByRoleId(role.getId());
for (AdminPermission permission : permissionList){
permissions.add(permission.getPercode());
}
}
//将set转成string
List permissionsToClaims = new ArrayList(permissions);
claims.put(Constant.JWT_PERMISSIONS_KEY, permissionsToClaims);
claims.put(Constant.JWT_USER_NAME, user.getUsername());
//accessToken 中传入adminuser的id和claims
String accessToken = JwtUtils.getAccessToken(String.valueOf(user_id), claims);
//创建 refreshToken 存入redis
//具体逻辑尚未实现
String refreshToken = JwtUtils.getRefreshToken(String.valueOf(user_id),claims);
//输出登录ip(为功能升级做准备)
String ip = WebUtils.getRequest().getRemoteAddr();
log.info("登录人" + username + "的IP为" + ip);
return new ResultObj(Constant.OK, Constant.LOGIN_SUCCESS, accessToken);
}
//不能注册成Bean不然springboot会先接手这个bean,然后原先的公共资源就不能访问了
//@Bean
//public JwtFilter jwtFilter() {
// return new JwtFilter();
//}
在配置自己的过滤器的时候不能采用注入的方式,因为如果你用了Bean注入,这个过滤器就交给shiro管理了,这样的话你的配置就会乱了,所有在shiroconfig中采用new的方式注入filter
将系统用户与角色的关系从多对一变成了多对多
原先在AdminUser表中写死了每个系统用户的角色
现在改成了一个系统用户可以拥有多个角色
从AdminUser中删除了role_id字段
添加了remark备注字段
抽离出来了一张admin_user_role字段
修改了查询用户的语句
首先是因为我返回的available属性是bool,再表格里直接这样写就显示不出来,经过查阅文档发现这样子需要对数据进行formatter
但是我又不想对子组件写死太多的规则,我更希望我对这个表格二次封装的组件有更高的自由度,经过查阅相关资料后我成功的实现了
只要在父组件实现formatter,传给子组件交给子组件去调用就好了
代码如下
父组件格式化代码,要加一个回调让子组件还可以收到value
//表格数据格式化
formatUserForm(row, column, value, callback) {
// console.log("start format");
// console.log(column)
let returnval;
if (column.property === "available") {
if (value === true) {
returnval = "可用";
} else {
returnval = "不可用";
}
} else {
returnval = value;
}
// let res = '';
callback(returnval);
},
子组件中检测有没有这个属性,如果有就采用父组件的格式化方法,没有就全部按照string 输出
还有好多东西要写,但是晚上学校断网,手机链热点老是抽风,明天再写