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