MySQL database table: teacher (user), role (role),perms (permission)

The teacher table

Role table

Perms table

Shiro is a security framework for authentication, authorization, password encryption, and session management.

Subject: the Subject represents the current “user”. This user is not necessarily a specific person. Anything that interacts with the current application is a Subject, such as web crawlers, robots, etc. It’s an abstract concept; All subjects are bound to the SecurityManager, and all interactions with the Subject are delegated to the SecurityManager; You can think of a Subject as a facade; The SecurityManager is the actual enforcer;

SecurityManager: SecurityManager; That is, all security-related operations interact with the SecurityManager; And it manages all subjects; As you can see, this is the core of Shiro. It is responsible for interacting with the other components described later. If you have learned SpringMVC, you can think of it as a DispatcherServlet front-end controller.

Realm: realms. Shiro gets security data (such as users, roles, and permissions) from a Realm. This means that SecurityManager needs to authenticate a user, then it needs to get the corresponding user from a Realm and compare it to determine if the user’s identity is valid. You also need to get the user’s roles/permissions from the Realm to verify that the user can perform operations; A Realm can be thought of as a DataSource, a secure DataSource.

Use:

Introduction of depend on

</dependency> <! <groupId>org.apache.shiro</groupId> <artifactId> <version>1.4. 0</version>
</dependency>
Copy the code

Rely on other

<! <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> <version>2.11..RELEASE</version> <! Use shiro tags - thymeleaf page - > < the dependency > < groupId > com. Making. Theborakompanioni < / groupId > <artifactId>thymeleaf-extras-shiro</artifactId> <version>2.0. 0</version> </dependency> <! -- Shiro integrated EhCache -->Copy the code

Configure the ShiroConfig class and custom Realm

ShiroConfig starts with three beans

/ / create ShiroFilterFactoryBean
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    // Set the security manager
    shiroFilterFactoryBean.setSecurityManager(securityManager);

    // Add Shiro built-in filters
    /*Shiro has built-in filters that implement permit-related interceptors * anon: the resource can be accessed without authentication * authc: the resource must be authenticated * user: the resource can be accessed directly if you use the rememberMe function * perms: The resource can be accessed only if the resource has been granted resource permission * role: the resource can be accessed only if the role permission has been granted * * */
    Map<String,String> filterMap = new LinkedHashMap<>();
    filterMap.put("/test"."anon");
    filterMap.put("/login"."anon");
    filterMap.put("/doRegister"."anon");
    filterMap.put("/register"."anon");
    // Authorization filter
    // Current authorization is blocked and Shiro automatically jumps to the unauthorized page
    filterMap.put("/add"."perms[user:add]");
    filterMap.put("/update"."perms[user:update]");
    filterMap.put("/ *"."authc");
    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
    // Default to login. JSP, change to toLogin
    shiroFilterFactoryBean.setLoginUrl("/toLogin");
    // Set the unauthorized page
    shiroFilterFactoryBean.setUnauthorizedUrl("/unAuth");
    return shiroFilterFactoryBean;
}
Copy the code
/ / create DefaultWebSecurityManager
@Bean("securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    / / associated Realm
    securityManager.setRealm(userRealm);
    //
    securityManager.setSessionManager( getDefaultWebSessionManager() );
    return securityManager;
}
/ / create a Realm
@Bean("userRealm")
public UserRealm getRealm(a){
    return new UserRealm();
}
Copy the code

Custom Realm Userrealm. Java

Inheritance: Extends AuthorizingRealm overrides two methods

// Execute the authorization logic
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    System.out.println("Enforcement authorization");
    return null;
}
// Execute authentication logic
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
    System.out.println("Performing certification"); 
}
Copy the code

Ctrl layer

Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(name,password);
Copy the code

Log on to the subject. The login (token);

Appropriate subject. Logout ();

Rights management Obtain role and rights during authentication

List<Role> rlist = rMapper.roleList(login.getRid());// Obtain the user role
List<Perms> plist = pMapper.permList(login.getRid());// Obtain user rights
List<String> roleStrlist=new ArrayList<>();//// User role set
List<String> perminsStrlist=new ArrayList<>();// Set of permissions for the user
for (Role role : rlist) {
    roleStrlist.add(role.getRole_name());
}
for(Perms uPermission : plist) { perminsStrlist.add(uPermission.getPerm()); } login.setRoleStrlist(roleStrlist); login.setPerminsStrlist(perminsStrlist); Add permission when authorization SimpleAuthorizationInfo info =new SimpleAuthorizationInfo();
// Set of user roles
info.addRoles(teacher.getRoleStrlist());
// Set of permissions for the userinfo.addStringPermissions(teacher.getPerminsStrlist()); Add two beans to the Shiroconfig class, define the encryption method, and inject@Bean("hashedCredentialsMatcher")
public HashedCredentialsMatcher hashedCredentialsMatcher(a) {
    HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
    hashedCredentialsMatcher.setHashAlgorithmName("MD5");// Hash algorithm: MD5 algorithm is used here;
    hashedCredentialsMatcher.setHashIterations(1024);// The number of hashes, such as two hashes, is equivalent to md5(md5(""));
    hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);// Hexadecimal or not
    return hashedCredentialsMatcher;
}
/** * authentication realm */
@Bean("myShiroRealm")
public UserRealm myShiroRealm(a){
    UserRealm myShiroRealm = new UserRealm();
    myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
    System.out.println("MyShiroRealm injection successful");
    returnmyShiroRealm; } SimpleAuthenticationInfo info = for Realm authenticationnull;
     String realname = getName();
    // The salt value is encrypted. The user name can be used
    ByteSource salt = ByteSource.Util.bytes(tname);
    info = new SimpleAuthenticationInfo(login,login.getPassword(),salt, realname);
Session session = SecurityUtils.getSubject().getSession();
session.setAttribute("USER_SESSION", login); Salt: Increases the complexity of encryption and adds hashCopy the code

MD5 encryption method in Shiro

ByteSource credentialsSalt01 = ByteSource.Util.bytes("Zhang");
Object credential = "123456";/ / password
String hashAlgorithmName = "MD5";// Encryption mode
//1024 indicates the number of times of encryption
Object simpleHash = new SimpleHash(hashAlgorithmName, credential,
        credentialsSalt01, 1024);
System.out.println("Encrypted value ----->" + simpleHash)
Copy the code

Caching mechanisms

Why cache? On the page to access some role or permissions to access the url, you will find that every visit to take corresponding to the role of the users to have access to the database, imagine, every time I visit a url, repeated to the database with these data, is clearly a not mature practice, if a cache, we only need to query a database, After that, all access to the URL will take data from the cache rather than the database, which will significantly reduce database pressure and look relatively mature. Add the dependent

Add bean Shiroconfig@Bean
public EhCacheManager getCacheManager(a){
    EhCacheManager ehCacheManager = new EhCacheManager();
    //ehCacheManager.setCacheManagerConfigFile("src\\main\\resources\\shiro-ehcache.xml");
    returnehCacheManager; } is added to the securityManager securityManager. SetCacheManager (getCacheManager ()); Log in to Shiroconfig again// Prohibit repeat logins
/ / configuration sessionDAO
@Bean(name="sessionDAO")
public MemorySessionDAO getMemorySessionDAO(a){
    MemorySessionDAO sessionDAO = new MemorySessionDAO();
    return sessionDAO;
}

// Configure a manager for Shiro sessions
@Bean(name = "sessionManager")
public DefaultWebSessionManager getDefaultWebSessionManager(a){
    DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
    // Set the session expiration time
    sessionManager.setGlobalSessionTimeout(60*60*1000);
    // Look at the code
    sessionManager.setSessionDAO(getMemorySessionDAO());
    // Resolve the issue of urls carrying JessionIds
    sessionManager.setSessionIdUrlRewritingEnabled(false);
    returnsessionManager; } Realm: delete session// Prohibit simultaneous login
if( tname.equals( login.getName() ) && md5.equals( login.getPassword() ) ){
    // Get all sessions
    Collection<Session> sessions = sessionDAO.getActiveSessions();
    for (Session session: sessions) {
        Teacher sysUser = (Teacher) session.getAttribute("USER_SESSION");
        // If there is a current login in the session, then it is proved that the login is repeated, then it is removed
        System.out.println("seesion:"+session.getId());
        if( sysUser! =null) {if( tname.equals( sysUser.getName() ) ){
                session.setTimeout(0); }}}}Copy the code

other

// Configure ShiroDialect for thymeleaf and Shiro tags
@Bean
public ShiroDialect getShiroDialect(a){
    return new ShiroDialect();
}
Copy the code