shiro的demo很多,我也看了很多,基本掌握了用法,而去基于shiro做一部分按需定制的开发还是感觉有些难度.
这个例子是这样的:
1.会员登录前端网站,需按照其等级分配权限,查看网站上的数据(低等级不展示具体数值,反之)
2.管理员等角色登录网站后端,进行后端权限操作分配.(除了样式没设置,其它的都还可以了)
我认为的改变是从ShiroConfiguration这个配置类着手,code 如下
/**
* ShiroFilterFactoryBean 处理拦截资源文件问题。
* 注意:单独一个ShiroFilterFactoryBean配置是或报错的,因为在
* 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager
* <p>
* Filter Chain定义说明
* 1、一个URL可以配置多个Filter,使用逗号分隔
* 2、当设置多个过滤器时,全部验证通过,才视为通过
* 3、部分过滤器可指定参数,如perms,roles
*/
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
System.out.println("ShiroConfiguration.shirFilter()");
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//TODO 2019-1-29 17:40
//将设置url的参数改为application.properties中去配置
//securityManager改为可选择的进行传入
//customisedFilter的hashmap传入的url及URLPath...Filter改为参数可传入
//customisedFilter这个HashMap装配了登录及登录后可未授权页面(admin的配置admin的,member的配置member的)
//filterChainDefinitionMap
//1.securityManager中的realm按需配置
//2.shiroFilterFactoryBean中的set...Url为按需配置
//3.shiroFilterFactoryBean.setFilters(customisedFilter);中的customisedFilter按需配置
//**customisedFilter为put了仅仅一个"url",value为URL路径匹配过滤器(按需传入)
//4.shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
//**filterChainDefinitionMap为按需配置
// 必须设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl("/admin/login"); //原为/login
// 登录成功后要跳转的链接
shiroFilterFactoryBean.setSuccessUrl("/admin/"); //原为/index
//未授权界面;
shiroFilterFactoryBean.setUnauthorizedUrl("/admin/unauthorized"); //原为/unauthorized
//拦截器.
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
//自定义拦截器
Map<String, Filter> customisedFilter = new HashMap<>();
customisedFilter.put("url", getURLPathMatchingFilter());
//配置映射关系 anon表示不需要权限即可访问
filterChainDefinitionMap.put("/admin/login", "anon");
// filterChainDefinitionMap.put("/admin/index", "anon");
filterChainDefinitionMap.put("/static/**", "anon");
filterChainDefinitionMap.put("/admin/config/**", "anon");
filterChainDefinitionMap.put("/admin/doLogout", "logout");
;//后台登出
// 单独放入member的配置中 filterChainDefinitionMap.put("/member/doLogout","logout");//前端客户登出
filterChainDefinitionMap.put("/admin/**", "url"); //路径/shiro_admin/**全部需要进行权限验证
//其他资源都需要认证 authc 表示需要认证才能进行访问 user表示配置记住我或认证通过可以访问的地址
filterChainDefinitionMap.put("/admin/**", "user");
shiroFilterFactoryBean.setFilters(customisedFilter);
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
要分别设定其权限及验证有github上的一些demo可以参考,但不同的是没有了这些路径拦截配置.
ShiroFilterFactoryBean中有些数值的getter setter从这里入手,并重写FilterChainManager应该可以完成路径的自由配置:
同理可得重写ShiroFilterFactoryBean也一样会设定自由路径的配置:
首先第一步,在重写的CustomShiroFilterFactoryBean中,我们要设置参数的可判定性,因为上方中的loginUrl...包括put到filterChainDefinitionMap中的路径等都是固定的,我们要根据判断的用户类型去配给不同的路径.(当然这样做后在实际应用场景中是否能奏效还待考量)
根据这种思路改变的MyRealm
package com.tansuo365.test1.realm;
import com.tansuo365.test1.bean.Member;
import com.tansuo365.test1.bean.User;
import com.tansuo365.test1.entity.MyLoginInstance;
import com.tansuo365.test1.service.*;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Set;
@Component
public class MyRealm extends AuthorizingRealm {
@Autowired
private MemberService memberService;//member
@Autowired
private UserService userService;//user
@Autowired
private MroleService mroleService;//member
@Autowired
private RoleService roleService; //user
@Autowired
private MemberPermissionService memberPermissionService;//member
@Autowired
private PermissionService permissionService;//user
/*获取授权权限信息*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo info = null;
//获取当前登录类型
String loginType = (String)SecurityUtils.getSubject().getSession().getAttribute("loginType");
Set<String> permissions = null;
Set<String> roles = null;
// 能进入到这里,表示账号已经通过验证了
String username = (String)principals.getPrimaryPrincipal();
if(LoginEnum.ADMIN.toString().equals(loginType)){
permissions = permissionService.listPermissions(username);
roles = roleService.listRoleNames(username);
}
if(LoginEnum.MEMBER.toString().equals(loginType)){
// Member member = memberService.getByName(username);
// 通过service获取角色和权限
permissions = memberPermissionService.listMemberPermissions(username);
roles = mroleService.listMroleNames(username);
}
// 授权对象
info = new SimpleAuthorizationInfo();
// 把通过se