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頁面

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM