The next day learning shiro

Shiro yesterday talked about the certification process and code implementation, this will be extended today.

Because our test data is shiro.ini file configured static data, but in fact the data from the database query should be reasonable, so we talk about the use of JdbcRealm today.

The jar package required as follows:

commons-beanutils-1.9.3.jar
commons-logging-1.2.jar
jcl-over-slf4j-1.7.12.jar
log4j-1.2.16.jar
shiro-all-1.4.1.jar
slf4j-api-1.7.25.jar
slf4j-log4j12-1.6.4.jar
mysql-connector-java-5.1.47.jar
mchange-commons-java-0.2.11.jar
c3p0-0.9.5.2.jar

 

IniSecurityManagerFactory part of the source code:

    public static final String MAIN_SECTION_NAME = "main";

    public static final String SECURITY_MANAGER_NAME = "securityManager";
    public static final String INI_REALM_NAME = "iniRealm";
   
    ......
    protected Map<String, ?> createDefaults(Ini ini, Ini.Section mainSection) {
        Map<String, Object> defaults = new LinkedHashMap<String, Object>();

        SecurityManager securityManager = createDefaultInstance();
        defaults.put(SECURITY_MANAGER_NAME, securityManager);

        if (shouldImplicitlyCreateRealm(ini)) {
            Realm realm = createRealm(ini);
            if (realm != null) {
                defaults.put(INI_REALM_NAME, realm);
            }
        }
    ......

You can see from this source, IniSecurityManagerFactory default settings to the iniRealm SecurityManager at the time of initialization, unless we ourselves set up to use SecurityManager which realm, it gets judged realm is not empty, we will set our realm is set to SecurityManager, so we to configure a new realm that is JdbcRealm in shiro.ini in.

JdbcRealm part of the source code:

/**
     * The default query used to retrieve account data for the user.
     */
    protected static final String DEFAULT_AUTHENTICATION_QUERY = "select password from users where username = ?";
    
    /**
     * The default query used to retrieve account data for the user when {@link #saltStyle} is COLUMN.
     */
    protected static final String DEFAULT_SALTED_AUTHENTICATION_QUERY = "select password, password_salt from users where username = ?";

    /**
     * The default query used to retrieve the roles that apply to a user.
     */
    protected static final String DEFAULT_USER_ROLES_QUERY = "select role_name from user_roles where username = ?";

    /**
     * The default query used to retrieve permissions that apply to a particular role.
     */
    protected static final String DEFAULT_PERMISSIONS_QUERY = "select permission from roles_permissions where role_name = ?";

......
 public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }
......
 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String username = upToken.getUsername();

        // Null username is invalid
        if (username == null) {
            throw new AccountException("Null usernames are not allowed by this realm.");
        }

        Connection conn = null;
        SimpleAuthenticationInfo info = null;
        try {
            conn = dataSource.getConnection();

            String password = null;
            String salt = null;
            switch (saltStyle) {
            case NO_SALT:
                password = getPasswordForUser(conn, username)[0];
                break;
            case CRYPT:
                // TODO: separate password and hash from getPasswordForUser[0]
                throw new ConfigurationException("Not implemented yet");
                //break;
            case COLUMN:
                String[] queryResults = getPasswordForUser(conn, username);
                password = queryResults[0];
                salt = queryResults[1];
                break;
            case EXTERNAL:
                password = getPasswordForUser(conn, username)[0];
                salt = getSaltForUser(username);
            }

            if (password == null) {
                throw new UnknownAccountException("No account found for user [" + username + "]");
            }

            info = new SimpleAuthenticationInfo(username, password.toCharArray(), getName());
            
            if (salt != null) {
                info.setCredentialsSalt(ByteSource.Util.bytes(salt));
            }

        } catch (SQLException e) {
            final String message = "There was a SQL error while authenticating user [" + username + "]";
            if (log.isErrorEnabled()) {
                log.error(message, e);
            }

            // Rethrow any SQL errors as an authentication exception
            throw new AuthenticationException(message, e);
        } finally {
            JdbcUtils.closeConnection(conn);
        }

        return info;
    }

From JdbcRealm source, we see a lot of sql statement, users are removed from the table in the query field username, password, password_salt and so on, but also appeared dataSource source, but we need this dataSource is set to go, so to use JdbcRealm, we must create the table users and the corresponding field in the database, we also need to inject JdbcRealm dataSource. Here we begin shiro.ini configuration file.

shiro.ini Bunken:

[main]
dataSource=com.mchange.v2.c3p0.ComboPooledDataSource
dataSource.driverClass=com.mysql.jdbc.Driver
dataSource.jdbcUrl=jdbc:mysql://localhost:3306/test
dataSource.user=root
dataSource.password=root
myRealm=org.apache.shiro.realm.jdbc.JdbcRealm
myRealm.dataSource=$dataSource
securityManager.realm=$myRealm

Almost forgot to say, in the shiro.ini file, there are many modules, such as yesterday [Users] used to store static data, and the above [main] is used to configure and it needs SecurityManager dependent components such as the realm module, of course, configure user roles module [role], we here do not speak, then left to the authorization module.

Learn the [main] application, we look at the above configuration, first we configure a dataSource (with here is the data source c3p0, remember to pack guide oh), including the configuration of its database-driven, Url, and database logins password, and then with a myRealm pointing JdbcRealm, then the above dataSource set to myRealm in order to achieve the injection of dataSource (where $ represents the injection, injection with spring similar to), then this myRealm set the default realm SecurityManager in order to complete the configuration.

Configuration is complete, then we have to create the users table in the database:

As shown, users create a table in the test database, which must include the field JdbcRealm class sql statement appeared, where we set up three.

You create the table, we start coding, the process is actually almost like the first day:

package test_JdbcRealm;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TestJdbcRealm {

    private static final Logger logger = LoggerFactory.getLogger(TestJdbcRealm.class ); 
    
    public  static  void main (String [] args) {
         // 1. Create securityManager plant 
        Factory's <the SecurityManager> Factory = new new IniSecurityManagerFactory ( "CLASSPATH: shiro.ini" );
         // 2. Examples securityManager obtaining 
        the SecurityManager securityManager = Factory .getInstance ();
         // 3. SecurityUtils the tool set to an instance SecurityManager class 
        SecurityUtils.setSecurityManager (securityManager);
         // . 4. Create a Subject instance 
        Subject Subject = SecurityUtils.getSubject ();
         // 5. The acquisition token, simulated user login
        = Token UsernamePasswordToken new new UsernamePasswordToken ( "zhangsan", "123456" );
         the try {
             // 6. The authentication token 
            subject.login (token);
             IF (subject.isAuthenticated ()) { 
                logger.info ( "login success" ); 
            } 
        } the catch (of AuthenticationException E) {
             // the TODO Auto-Generated Block the catch 
            e.printStackTrace (); 
            logger.error ( "user name or password, login failed" ); 
        } 
    } 
}
2019-07-25 23:30:43,705 INFO [com.mchange.v2.log.MLog] - MLog clients using slf4j logging. 
2019-07-25 23:30:44,102 INFO [com.mchange.v2.c3p0.C3P0Registry] - Initializing c3p0-0.9.5.2 [built 08-December-2015 22:06:04 -0800; debug? true; trace: 10] 
2019-07-25 23:30:44,211 INFO [org.apache.shiro.config.IniSecurityManagerFactory] - Realms have been explicitly set on the SecurityManager instance - auto-setting of realms will not occur. 
2019-07-25 23:30:44,233 INFO [com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource] - Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> 2zm2h8a4bl36b813yacsm|7e0ea639, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 2zm2h8a4bl36b813yacsm|7e0ea639, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost:3306/test, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 15, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ] 
2019-07-25 23:30:44,525 INFO [org.apache.shiro.session.mgt.AbstractValidatingSessionManager] -Validation Scheduler ... the session Enabling 
 2019-07-25 23: 30: 44,537 INFO [test_JdbcRealm.TestJdbcRealm] - successful landing

It is also a few steps, but in the instance of SecurityManager load profile generation is not the same, because we configured the default realm SecurityManager in the configuration file for the JdbcRealm, so when subjec.login (token) certification, will eventually to compare the authentication by the user authentication method JdbcRealm isolated on data from the database!

to sum up:

1. When using a class, we need the source code to understand what it takes before you can purposefully be configured as JdbcRealm this class, it needs a table and data sources to implement the query data out of the database for authentication ;

2.shiro.ini comprising a plurality of components such as the [main], [users], [role] as well as [URL], we need to understand the role and function of each main part;

3. We can learn from the examples above, SecurityManager can use to configure the realm! ! So it means that we can customize the realm to implement authentication and authorization logic! This part of the follow-up I learned will be shared.

These are my learning today resulting shiro, if you have any additions or suggestions, problems in the comments area, thank you!

Guess you like

Origin www.cnblogs.com/wujianwu/p/11247683.html