ToB企服应用市场:ToB评测及商务社交产业平台

标题: Shiro-00-shiro 概览 [打印本页]

作者: 涛声依旧在    时间: 2024-4-24 14:01
标题: Shiro-00-shiro 概览
RBAC

RBCA
RBCA zh_CN
Shiro

Apache Shiro 是一个强大且易于使用的 Java 安全框架,负责执行身份验证、授权、加密和会话管理。
通过 Shiro 的易于理解的 API,您可以快速而轻松地保护任何应用程序,从最小的移动应用到最大的 Web 和企业应用。
Shiro 提供了应用程序安全 API,用于执行以下方面:
    Subject->SecurityManager:    SecurityManager->Realms:
shiro
shiro zh_CN
Hello world

  1. <dependencies>
  2.     <dependency>
  3.         <groupId>junit</groupId>
  4.         <artifactId>junit</artifactId>
  5.         <version>4.9</version>
  6.     </dependency>
  7.     <dependency>
  8.         <groupId>commons-logging</groupId>
  9.         <artifactId>commons-logging</artifactId>
  10.         <version>1.1.3</version>
  11.     </dependency>
  12.     <dependency>
  13.         <groupId>org.apache.shiro</groupId>
  14.         <artifactId>shiro-core</artifactId>
  15.         <version>1.2.2</version>
  16.     </dependency>
  17. </dependencies>
复制代码
create this file under the classpath.
  1. [users]
  2. ryo=123
  3. wang=123
复制代码
  1. @Test
  2. public void testHelloworld() {
  3.     Factory<SecurityManager> factory =
  4.             new IniSecurityManagerFactory("classpath:shiro.ini");
  5.     org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
  6.     SecurityUtils.setSecurityManager(securityManager);
  7.     Subject subject = SecurityUtils.getSubject();
  8.     UsernamePasswordToken token = new UsernamePasswordToken("ryo", "123");
  9.     try {
  10.         subject.login(token);
  11.     } catch (AuthenticationException e) {
  12.         //login falied
  13.     }
  14.    assertEquals(true, subject.isAuthenticated());   //assert user has logined.
  15.    //logout
  16.    subject.logout();
  17. }
复制代码
Realms

Realms(领域)充当 Shiro 与您的应用程序安全数据之间的“桥梁”或“连接器”。
当需要实际与安全相关的数据进行交互,例如从用户帐户执行身份验证(登录)和授权(访问控制)时,Shiro 会查找配置为应用程序的一个或多个领域中的许多信息。
  1. public interface Realm {
  2.     String getName();   //返回一个唯一的Realm名字
  3.     boolean supports(AuthenticationToken var1); //判断此Realm是否支持此Token
  4.     AuthenticationInfo getAuthenticationInfo(AuthenticationToken var1) throws AuthenticationException;  //根据Token获取认证信息
  5. }
复制代码
  1. public class MyRealm implements Realm {
  2.     @Override
  3.     public String getName() {
  4.         return "firstRealm";
  5.     }
  6.     @Override
  7.     public boolean supports(AuthenticationToken authenticationToken) {
  8.         //仅支持UsernamePasswordToken类型的Token
  9.         return authenticationToken instanceof UsernamePasswordToken;
  10.     }
  11.     @Override
  12.     public AuthenticationInfo getAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
  13.         String username = (String) authenticationToken.getPrincipal();      //get username
  14.         String password = new String((char[]) authenticationToken.getCredentials());    //get password
  15.         if (!"ryo".equals(username)) {
  16.             throw new UnknownAccountException();
  17.         }
  18.         if (!"123".equals(password)) {
  19.             throw new IncorrectCredentialsException();
  20.         }
  21.         //如果身份认证验证成功,返回一个AuthenticationInfo实现;
  22.         return new SimpleAuthenticationInfo(username, password, getName());
  23.     }
  24. }
复制代码
create this file under the classpath.
  1. #declear realm
  2. firstRealm=com.ryo.shiro.MyRealm
  3. #point the realms impls of securityManager
  4. securityManager.realms=$firstRealm
复制代码
  1. @Test
  2. public void testRealm() {
  3.     Factory<SecurityManager> factory =
  4.             new IniSecurityManagerFactory("classpath:shiro-realm.ini");
  5.     org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
  6.     SecurityUtils.setSecurityManager(securityManager);
  7.     Subject subject = SecurityUtils.getSubject();
  8.     UsernamePasswordToken token = new UsernamePasswordToken("ryo", "123");
  9.     try {
  10.         subject.login(token);
  11.     } catch (AuthenticationException e) {
  12.     }
  13.     assertEquals(true, subject.isAuthenticated());
  14.     subject.logout();
  15. }
复制代码
multi-realm

  1. public class SecondRealm implements Realm {
  2.     public String getName() {
  3.         return "secondRealm";
  4.     }
  5.     public boolean supports(AuthenticationToken authenticationToken) {
  6.         return authenticationToken instanceof UsernamePasswordToken;
  7.     }
  8.     public AuthenticationInfo getAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
  9.         String username = (String) authenticationToken.getPrincipal();
  10.         String password = new String((char[]) authenticationToken.getCredentials());
  11.         if (!"wang".equals(username)) {
  12.             throw new UnknownAccountException();
  13.         }
  14.         if (!"123".equals(password)) {
  15.             throw new IncorrectCredentialsException();
  16.         }
  17.         return new SimpleAuthenticationInfo(username, password, getName());
  18.     }
  19. }
复制代码
  1. [main]
  2. #define
  3. firstRealm=com.ryo.shiro.FirstRealm
  4. secondRealm=com.ryo.shiro.SecondRealm
  5. #use
  6. securityManager.realms=$firstRealm,$secondRealm
复制代码
  1. @Test
  2. public void testMultiRealm() {
  3.     Factory<SecurityManager> factory =
  4.             new IniSecurityManagerFactory("classpath:shiro-multi-realm.ini");
  5.     org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
  6.     SecurityUtils.setSecurityManager(securityManager);
  7.     Subject subject = SecurityUtils.getSubject();
  8.     UsernamePasswordToken token = new UsernamePasswordToken("wang", "123");
  9.     try {
  10.         subject.login(token);
  11.     } catch (AuthenticationException e) {
  12.         e.printStackTrace();
  13.     }
  14.     Assert.assertEquals(true, subject.isAuthenticated());
  15.     subject.logout();
  16. }
复制代码
Notice
The realm worked only after you used it.
JDBC Realm

  1. <dependency>
  2.     <groupId>mysql</groupId>
  3.     <artifactId>mysql-connector-java</artifactId>
  4.     <version>5.1.25</version>
  5. </dependency>
  6. <dependency>
  7.     <groupId>com.alibaba</groupId>
  8.     <artifactId>druid</artifactId>
  9.     <version>0.2.23</version>
  10. </dependency>
复制代码
  1. DROP DATABASE IF EXISTS shiro;
  2. CREATE DATABASE shiro;
  3. USE shiro;
  4. CREATE TABLE users (
  5.   id            BIGINT AUTO_INCREMENT,
  6.   username      VARCHAR(100),
  7.   password      VARCHAR(100),
  8.   password_salt VARCHAR(100),
  9.   CONSTRAINT pk_users PRIMARY KEY (id)
  10. )
  11.   CHARSET = utf8
  12.   ENGINE = InnoDB;
  13. CREATE UNIQUE INDEX idx_users_username ON users (username);
  14. CREATE TABLE user_roles (
  15.   id        BIGINT AUTO_INCREMENT,
  16.   username  VARCHAR(100),
  17.   role_name VARCHAR(100),
  18.   CONSTRAINT pk_user_roles PRIMARY KEY (id)
  19. )
  20.   CHARSET = utf8
  21.   ENGINE = InnoDB;
  22. CREATE UNIQUE INDEX idx_user_roles ON user_roles (username, role_name);
  23. CREATE TABLE roles_permissions (
  24.   id         BIGINT AUTO_INCREMENT,
  25.   role_name  VARCHAR(100),
  26.   permission VARCHAR(100),
  27.   CONSTRAINT pk_roles_permissions PRIMARY KEY (id)
  28. )
  29.   CHARSET = utf8
  30.   ENGINE = InnoDB;
  31. CREATE UNIQUE INDEX idx_roles_permissions ON roles_permissions (role_name, permission);
  32. INSERT INTO users (username, password) VALUES ('wang', '123');
  33. INSERT INTO users (username, password) VALUES ('ryo', '123');
复制代码
  1. [main]
  2. jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
  3. dataSource=com.alibaba.druid.pool.DruidDataSource
  4. dataSource.driverClassName=com.mysql.jdbc.Driver
  5. dataSource.url=jdbc:mysql://localhost:3307/shiro
  6. dataSource.username=root
  7. dataSource.password=${youOwnSQLPassword}
  8. jdbcRealm.dataSource=$dataSource
  9. securityManager.realms=$jdbcRealm
  10. ;1、varName=className    auto create an instance of class.
  11. ;2、varName.property=val         auto call the set()
  12. ;3、$varname             reference an object define before;
复制代码
  1. @Test
  2. public void testJDBCRealm() {
  3.     Factory<org.apache.shiro.mgt.SecurityManager> factory =
  4.             new IniSecurityManagerFactory("classpath:shiro-jdbc-realm.ini");
  5.     org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
  6.     SecurityUtils.setSecurityManager(securityManager);
  7.     Subject subject = SecurityUtils.getSubject();
  8.     UsernamePasswordToken token = new UsernamePasswordToken("ryo", "123");
  9.     try {
  10.         subject.login(token);
  11.     } catch (AuthenticationException e) {
  12.         e.printStackTrace();
  13.     }
  14.     Assert.assertEquals(true, subject.isAuthenticated());
  15.     subject.logout();
  16. }
复制代码
Authenticator

  1. [main]
  2. authenticator = com.foo.bar.CustomAuthenticator
  3. securityManager.authenticator = $authenticator
复制代码
SecurityManager.java
  1. public interface SecurityManager extends Authenticator, Authorizer, SessionManager {
  2. }
复制代码
Authenticator.java
  1. public interface Authenticator {
  2.     AuthenticationInfo authenticate(AuthenticationToken var1) throws AuthenticationException;
  3. }
复制代码
AuthenticationStrategy

当为应用程序配置了两个或更多领域时,ModularRealmAuthenticator 依赖于内部的 AuthenticationStrategy 组件来确定身份验证尝试成功或失败的条件。
        AuthenticationStrategy 类        描述                AtLeastOneSuccessfulStrategy        如果一个或多个领域成功验证,则将考虑整体尝试成功。如果没有一个验证成功,则尝试失败。                FirstSuccessfulStrategy        仅使用从第一个成功验证的领域返回的信息。所有后续领域将被忽略。如果没有一个验证成功,则尝试失败。                AllSuccessfulStrategy        所有配置的领域必须成功验证才能考虑整体尝试成功。如果有任何一个验证不成功,则尝试失败。    1、这里定义了三个用于测试的领域:
2、shiro-authenticator-all-success.ini
ModularRealmAuthenticator 默认使用 AtLeastOneSuccessfulStrategy 实现,因为这是最常用的策略。
但是,如果需要,您可以配置不同的策略。
  1. [main]
  2. #point out securityManager's authenticator  
  3. authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator  
  4. securityManager.authenticator=$authenticator  
  5.   
  6. #Point out securityManager.authenticator's authenticationStrategy  
  7. allSuccessfulStrategy=org.apache.shiro.authc.pam.AllSuccessfulStrategy  
  8. securityManager.authenticator.authenticationStrategy=$allSuccessfulStrategy  
  9. #Define and use realms
  10. firstRealm=com.ryo.shiro.FirstRealm
  11. secondRealm=com.ryo.shiro.SecondRealm
  12. thirdRealm=com.ryo.shiro.ThirdRealm
  13. securityManager.realms=$firstRealm,$thirdRealm
复制代码
3、AuthenticatorTest.java
  1. @Test
  2. public void testAllSuccessfulStrategyWithSuccess() {
  3.     Subject subject = getSubjectByPath("classpath:shiro-authenticator-all-success.ini");
  4.     UsernamePasswordToken token = new UsernamePasswordToken("ryo", "123");
  5.     subject.login(token);
  6.     PrincipalCollection principalCollection = subject.getPrincipals();
  7.     assertEquals("ryo,ryo@gmail.com", principalCollection.toString());
  8. }
  9. private Subject getSubjectByPath(String configFilePath) {
  10.     Factory<SecurityManager> factory = new IniSecurityManagerFactory(configFilePath);
  11.     SecurityManager securityManager = factory.getInstance();
  12.     SecurityUtils.setSecurityManager(securityManager);
  13.     return SecurityUtils.getSubject();
  14. }
复制代码
提示
如果您想自己创建自己的 AuthenticationStrategy 实现,您可以使用 org.apache.shiro.authc.pam.AbstractAuthenticationStrategy 作为起点。
[code]public class OnlyOneAuthenticatorStrategy extends AbstractAuthenticationStrategy {    //Simply returns the aggregate argument without modification.    @Override    public AuthenticationInfo beforeAllAttempts(Collection




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4