上篇谈到shiro利用doGetAuthenticationInfo方法来实现用户的认证
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
String username=token.getUsername();//获取页面中传递的用户账号
String password=new String(token.getPassword());//获取页面
}
可以拿到我们登陆时的用户名和密码来进行判断与数据库中响应用户的加盐(yan)密码是否匹配。
以及用doGetAuthorizationInfo实现用户的授权
//获取用户的账号,根据账号来从数据库中获取数据
Object obj = principalCollection.getPrimaryPrincipal();
//定义用户角色的set集合这个集合应该来自数据库
Set<String> roles = new HashSet<>();
if("admin".equals(obj)){
System.out.println(" --- 授权了admin --------");
roles.add("admin");
roles.add("user");
}
if("user".equals(obj)){
System.out.println(" --- 授权了user --------" + obj);
roles.add("user");
}
Set<String> permissions = new HashSet<>();
if("admin".equals(obj)){
//添加一个权限admin:add 只是一种命名风格表示admin下的add功能
permissions.add("admin:add");
}
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
info.setRoles(roles);
info.setStringPermissions(permissions);
return info;
=******************************************************************=
在授权的时候其实不是只能使用set集合这个方式,通过info.setRoles(roleSet)或者 info.setStringPermissions(permissionsSet)
这种实现起来的方式只是在对于特别少的用户或者测试的时候使用。那么我们的实际开发中数据肯定都是保存在数据库中的。如何将查询出来的数据来指定这种用户角色权限的控制呢?
依然是我们的授权方法doGetAuthorizationInfo
//获取当前登录的对象
Subject subject = SecurityUtils.getSubject();
注意 : 这里的subject并不是说只能取到登录用户名,判断的依据来源于你在登录的时候构建的简易对象是什么。
在realm中我们的登录步骤是获取到当前页面输入的token
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
那么你在去数据库中查询的时候查出来的User
User user = userService.selectUserByTerms(userToken.getUsername(), null);
最后是通过SimpleAuthenticationInfo 来构建一个登录的简易对象。
1、第一种
return new SimpleAuthenticationInfo(user, user.getPassword(), "");
2、第二种
return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), "");
这两种方式的比较在于第一个参数到底你传的是什么是一个User对象还是只传用户名。那么对于在doGetAuthorizationInfo授权方法中那取的时候当前subject拿到的就是这个传递的参数。
1、如果是第一种:
User loginUser= (User) subject.getPrincipal();
1、如果是第二种:
String currentUserUsername= ((User) subject.getPrincipal()).getUsername();
以角色为例吧,权限的写法类似
第一种写法:
//创建一个set集合
Set<String> roles = new HashSet<>();
roles.add("admin");
roles.add("user");
第二种写法:
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addRole("admin");
info.addRole("user");
//当然 info.addRoles(collection roles) 一次性通过集合传入也是可以的
/**
* 开启Shiro注解支持(例如@RequiresRoles()和@RequiresPermissions())
* shiro的注解需要借助Spring的AOP来实现
* @return
*/
@Bean
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
return defaultAdvisorAutoProxyCreator;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
需要我们开启SpringAOP的支持,同时之前手动配置的路径权限就要注释掉。我们之间在方法上面实现方法粒度的权限
//需要admin角色 可以指定多个以逗号区分
@RequiresRoles(value = {"admin"})
// 需要admin:add权限 可以指定多个以逗号区分
@RequiresPermissions(value={"admin:add"})
在自定义的shiroConfig中配置
/**
* 配置Shiro标签与Thymeleaf的集成
* @return
*/
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
用法:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--基于属性的shiro标签-->
<h1 shiro:guest="true"> 没有登录</h1>
<!--基于标签的-->
<shiro:authenticated>
<h1>登录成功</h1><br>
</shiro:authenticated>
<shiro:user>
<h1>记住我</h1><br>
</shiro:user>
<shiro:notAuthenticated>
我还没有登录,没有调用subject.login()<br>
</shiro:notAuthenticated>
<shiro:principal>
</shiro:principal>
<br><br>
<shiro:hasRole name="admin">
有admin角色
</shiro:hasRole>
<shiro:lacksRole name="admin">
没有admin角色
</shiro:lacksRole>
<br><br>
<shiro:hasAnyRoles name="admin,user">
有admin | user 其中一个角色
</shiro:hasAnyRoles>
<br><br>
<shiro:hasAllRoles name="admin,user">
需要有 admin,user两个角色
</shiro:hasAllRoles>
<br><br>
<shiro:lacksPermission name="admin:add">
没有admin.add权限
</shiro:lacksPermission>
<br><br>
<shiro:hasPermission name="admin:add">
有admin.add权限
</shiro:hasPermission >
<br><br>
<shiro:hasAnyPermissions name="admin:add,admin:update">
有admin:add,admin:update其中一个权限
</shiro:hasAnyPermissions>
<br><br>
<shiro:hasAllPermissions name="admin:add,admin:update">
需要有admin:add,admin:update所有权限
</shiro:hasAllPermissions>
<h1><a href="/logout">登出</a><br><br><br></h1>
<a th:href="@{|/admin/test|}">需要有admin角色的功能</a><br>
<a th:href="@{|/admin/test01|}">需要有admin角色的功能test01</a><br>
<a th:href="@{|/admin/add|}">需要有admin角色的功能add</a><br>
<a th:href="@{|/user/test|}">需要有user角色的功能</a><br>
</body>
</html>
说明:
作为属性控制
<button type="button" shiro:authenticated="true">
权限控制
</button>
作为标签
<shiro:hasRole name="admin">
<button type="button">
权限控制
</button>
</shiro:hasRole>
guest标签
<shiro:guest>
</shiro:guest>
用户没有身份验证时显示相应信息,即游客访问信息。
user标签
<shiro:user>
</shiro:user>
用户已经身份验证/记住我登录后显示相应的信息。
authenticated标签
<shiro:authenticated>
</shiro:authenticated>
用户已经身份验证通过,即Subject.login登录成功,不是记住我登录的。
notAuthenticated标签
<shiro:notAuthenticated>
</shiro:notAuthenticated>
用户已经身份验证通过,即没有调用Subject.login进行登录,包括记住我自动登录的也属于未进行身份验证。
principal标签
<shiro:principal property="username">
<shiro:principal/>
相当于((User)Subject.getPrincipals()).getUsername()。
lacksPermission标签
<shiro:lacksPermission name="org:create">
</shiro:lacksPermission>
如果当前Subject没有权限将显示body体内容。
hasRole标签
<shiro:hasRole name="admin">
</shiro:hasRole>
如果当前Subject有角色将显示body体内容。
hasAnyRoles标签
<shiro:hasAnyRoles name="admin,user">
</shiro:hasAnyRoles>
如果当前Subject有任意一个角色(或的关系)将显示body体内容。
lacksRole标签
<shiro:lacksRole name="abc">
</shiro:lacksRole>
如果当前Subject没有角色将显示body体内容。
hasPermission标签
<shiro:hasPermission name="user:create">
</shiro:hasPermission>
如果当前Subject有权限将显示body体内容
<shiro:hasAnyPermissions name="admin:add,admin:update">
</shiro:hasAnyPermissions>
如果当前Subject有任意一个权限(或的关系)将显示body体内容。
<shiro:hasAllRoles name=""></shiro:hasAllRoles>
必须拥有指定的全选全部角色
<shiro:hasAllPermissions name=""></shiro:hasAllPermissions>
必须拥有指定的全选全部权限