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