shiro:多realm配置(链式、分支)

1、多realm配置相关概念

(1)使用场景、

当shiro进行权限管理的时候,数据来源于不同的数据源的时候,我们可以给安全管理器配置多个realm

  • 多个数据库
  • 多个数据表

(2)多个realm的处理方式

  • 链式处理

多个realm依次进行认证

  • 分支处理

根据不用的条件从多个realm中选择一个进行认证

2、链式

(1)定义多个realm

ManagerRealm:

public class ManagerRealm  extends AuthorizingRealm {
    Logger logger= LoggerFactory.getLogger(UserRealm.class);
    @Override
    public String getName(){
        return "ManagerRealm";
    }
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        logger.info("ManagerRealm---doGetAuthenticationInfo");
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String username=token.getUsername();
        SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(username,"123",getName());
        return info;
    }
}

UserRealm:

public class UserRealm extends AuthorizingRealm {
    Logger logger = LoggerFactory.getLogger(UserRealm.class);

    @Override
    public String getName() {
        return "UserRealm";
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        logger.info("UserRealm--doGetAuthenticationInfo");
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String username = token.getUsername();
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, "123456", getName());
        return info;
    }
}

(2)配置realm

书写配置类将定义的realm配置给安全管理器、配置过滤器:

@Configuration
public class ShiroConfig {
    @Bean
    public UserRealm userRealm() {
        UserRealm userRealm = new UserRealm();
        return userRealm;
    }

    @Bean
    public ManagerRealm managerRealm() {
        ManagerRealm managerRealm = new ManagerRealm();
        return managerRealm;
    }

    @Bean//安全管理器
    public DefaultWebSecurityManager getDefaultWebSecurityManager() {
        DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager();
        Collection<Realm> realms = new ArrayList<>();
        realms.add(userRealm());
        realms.add(managerRealm());
        defaultSecurityManager.setRealms(realms);
        return defaultSecurityManager;
    }

    @Bean//过滤器
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultSecurityManager securityManager) {
        ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean();
        filter.setSecurityManager(securityManager);
        Map<String, String> filterMap = new HashMap<>();
        filterMap.put("/", "anon");//anon表示不拦截(匿名用户可访问)
        filterMap.put("/login.html", "anon");
        filterMap.put("/user/login", "anon");
        filterMap.put("/user/regist", "anon");
        filterMap.put("/index.html", "user");
        filterMap.put("/**", "authc");
        filter.setFilterChainDefinitionMap(filterMap);
        filter.setLoginUrl("/login.html");
        filter.setUnauthorizedUrl("/login.html");
        return filter;
    }
}

(3)controller

页面跳转:

@Controller
public class PageController {
    @RequestMapping("/")
    public String Login1(){
        return "login";
    }
    @RequestMapping("/login.html")
    public String Login(){
        return "login";
    }
}

用户登录:

@Controller
@RequestMapping("user")
public class UserController {
    Logger logger=  LoggerFactory.getLogger(UserController.class);
    @RequestMapping("login")
    public String login(String username,String password,String loginType){
        logger.info("UserController--login");
        System.out.println(username+password);
        try {
            UsernamePasswordToken token=new UsernamePasswordToken(username,password);
            Subject subject= SecurityUtils.getSubject();
            subject.login(token);
            return "index";
        }catch (Exception e){
            return "login";
        }
    }
}

(4)页面

登录页:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
    <form action="/user/login">
        用户名:<input type="text" name="username"><br>
        密码:<input type="password" name="password"><br>
        <input type="radio" name="loginType" value="User"/>普通用户
        <input type="radio" name="loginType" value="Manager"/>管理员
        <input type="submit" value="登录">
    </form>
</body>
</html>

index页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
<h3>index</h3>
</body>
</html>

(5)测试

用户:

 管理员:

 这里并没有对用户的身份进行区分

3、分支

(1)自定义token

public class MyToken extends UsernamePasswordToken {
    private String loginType;
    public MyToken(String username, String password, String loginType) {
        super(username, password);
        this.loginType = loginType;
    }

    public String getLoginType() {
        return loginType;
    }

    public void setLoginType(String loginType) {
        this.loginType = loginType;
    }
}

(2)自定义ModularRealmAuthenticator

public class MyModularRealmAuthenticator extends ModularRealmAuthenticator {
    protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
        this.assertRealmsConfigured();
        Collection<Realm> realms = this.getRealms();
        MyToken token = (MyToken) authenticationToken;
        String loginType = token.getLoginType();
        Collection<Realm> typeRealms = new ArrayList<>();
        for (Realm realm : realms) {
            if (realm.getName().startsWith(loginType)) {
                typeRealms.add(realm);
            }
        }
        if (typeRealms.size() == 1) {
            return this.doSingleRealmAuthentication(typeRealms.iterator().next(), authenticationToken);
        } else {
            return this.doMultiRealmAuthentication(typeRealms, authenticationToken);
        }
    }
}

(3)配置类

@Configuration
public class ShiroConfig {
    @Bean
    public MyModularRealmAuthenticator myModularRealmAuthenticator(){
        MyModularRealmAuthenticator myModularRealmAuthenticator=new MyModularRealmAuthenticator();
        return myModularRealmAuthenticator;
    }

    @Bean
    public UserRealm userRealm() {
        UserRealm userRealm = new UserRealm();
        return userRealm;
    }

    @Bean
    public ManagerRealm managerRealm() {
        ManagerRealm managerRealm = new ManagerRealm();
        return managerRealm;
    }

    @Bean//安全管理器
    public DefaultWebSecurityManager getDefaultWebSecurityManager() {
        DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager();
        defaultSecurityManager.setAuthenticator(myModularRealmAuthenticator());
        Collection<Realm> realms = new ArrayList<>();
        realms.add(userRealm());
        realms.add(managerRealm());
        defaultSecurityManager.setRealms(realms);
        return defaultSecurityManager;
    }

    @Bean//过滤器
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultSecurityManager securityManager) {
        ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean();
        filter.setSecurityManager(securityManager);
        Map<String, String> filterMap = new HashMap<>();
        filterMap.put("/", "anon");//anon表示不拦截(匿名用户可访问)
        filterMap.put("/login.html", "anon");
        filterMap.put("/user/login", "anon");
        filterMap.put("/user/regist", "anon");
        filterMap.put("/index.html", "user");
        filterMap.put("/**", "authc");
        filter.setFilterChainDefinitionMap(filterMap);
        filter.setLoginUrl("/login.html");
        filter.setUnauthorizedUrl("/login.html");
        return filter;
    }
}

(4)controller

书写用户登录的controller,这里使用的是自定义token

@Controller
@RequestMapping("user")
public class UserController {
    Logger logger=  LoggerFactory.getLogger(UserController.class);
    @RequestMapping("login")
    public String login(String username,String password,String loginType){
        logger.info("UserController--login");
        System.out.println(username+password);
        try {
            MyToken token=new MyToken(username,password,loginType);
            Subject subject= SecurityUtils.getSubject();
            subject.login(token);
            return "index";
        }catch (Exception e){
            return "login";
        }
    }
}

(5)登录页

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
    <form action="/user/login">
        用户名:<input type="text" name="username"><br>
        密码:<input type="password" name="password"><br>
        <input type="radio" name="loginType" value="User" checked/>普通用户
        <input type="radio" name="loginType" value="Manager"/>管理员
        <input type="submit" value="登录">
    </form>
</body>
</html>

登录页可以选择用户的身份

(6)测试

以用户的用户名和密码进行登录,身份选择为用户:可以正常发进入index页面

以用户的用户名和密码进行登录,身份选择为管理员:不能进入index页面

原文地址:https://www.cnblogs.com/zhai1997/p/13757244.html