012springboot Shiro (security framework)

Posted by devxtech on Sat, 12 Feb 2022 17:55:38 +0100

catalogue

Shiro core three objects

Quickstart core:

First Shiro program

hello-shrio

1.pom.xml

2. Write Shiro configuration

log4j.properties

shiro.ini

3,Quickstart  

Core:

Shiro integrated in SpringBoot

Environment construction

 1.pom.xml

2.index.html

3.MyController

4.ShiroConfig realm object needs to be customized

5.UserRealm

6.ShiroConfig write backwards

 7. Add page

8. Test

User interception

Intercept: ShiroConfig--ShiroFilterFactoryBean

Jump to login page

Shrio uses user authentication

Shrio integrates Mybatis

1.pom.xml

2.application.yml 

3.pojo

        user

4.dao

        UserDao

        UserMapper

5.service

        UserService

        UserServiceImpl

Test: application tests

 6.UserRealm get data from database

Authorization

1. Authorize ShiroConfig--ShiroFilterFactoryBean

 2.noAuth.html # unauthorized page

3. Set unauthorized requests

 4. to grant authorization

 5. Get authorization from database

Permission selection

pom.xml

index.html

Login succeeded in obtaining session

Catalogue

ShiroConfig

UserRealm

MyController

Shiro core three objects

  1. Subject user
  2. SecurityManager manages all users
  3. Real connection data

Quickstart core:

//Get the current user object Subject
Subject currentUser = SecurityUtils.getSubject();
//Get session from current user
Session session = currentUser.getSession();
//Judge whether the user is authenticated
if (!currentUser.isAuthenticated()) { 


//Get the authentication access information of the current user
currentUser.getPrincipal() 
//Determine whether the user has a role
if (currentUser.hasRole("schwartz")) {
//Check whether you have any permissions
if (currentUser.isPermitted("lightsaber:wield")) { 
//Write off
currentUser.logout();
Shiro brief introduction
1.1 What is Shiro ?
  • Apache Shiro is a Java Security (permission) framework.
  • Shiro can easily develop good enough applications, which can be used not only in Java se environment, but also in Java EE environment.
  • Shiro can complete, authentication, authorization, encryption, session management, Web integration, caching, etc.
  • Download address: Apache Shiro | Simple. Java. Security.
  • GitHub: GitHub - apache/shiro: Apache Shiro
1.2 What are the functions?

  • Authentication: identity authentication, login, and verify whether the user has the corresponding identity;
  • Authorization: authorization, that is, permission verification. It verifies whether an authenticated user has a certain permission, that is, it determines whether the user can perform any operations, such as verifying whether a user has a certain role, or fine-grained verifying whether a user has a certain permission on a resource!
  • Session Manager: session management, that is, after a user logs in, it is the first session. Before exiting, all its information is in the session; The session can be an ordinary Java se environment or a Web environment;
  • Cryptography: encryption to protect the security of data. For example, the password is encrypted and stored in the database instead of plaintext;
  • Web Support: Web Support, which can be easily integrated into the web environment;
  • Caching: caching. For example, after a user logs in, the user information, roles and permissions do not need to be checked every time, which can improve efficiency
  • Concurrency: Shiro supports concurrent verification of multithreaded applications, that is, if you start another thread in one thread, you can automatically propagate permissions to the past
  • Testing: provide test support;
  • Run As: allow one user to pretend to be the identity of another user (if they allow it);
  • Remember Me: Remember Me, this is a very common function, that is, after logging in once, you don't need to log in next time

1.3 Shiro architecture (external)

From the outside Shiro , that is, how to use it from the perspective of application shiro finish the work

subject: The objects that application code directly interacts with are Subject , which means Shiro External API The core is Subject ,
Subject Represents the current user. This user is not necessarily a specific person. Anything interacting with the current application is
Subject , such as web crawlers, robots, etc Subject All interactions will be delegated to SecurityManager ; Subject his
It's really a facade, SecurityManageer Is the actual executor
SecurityManager: Security manager, that is, all security related operations will be associated with SercurityManager Interaction, and it
Managing all Subject , you can see that it is Shiro The core of it is responsible for working with Shiro Interact with other components of, which is equivalent to
SpringMVC of DispatcherServlet Role of
Realm : Shiro from Realm Obtain security data (such as users, roles and permissions), that is SecurityManager To verify
User identity, then it needs to be from Realm Obtain the corresponding users for comparison to determine whether the user's identity is legal; You also need to get the user's corresponding roles and permissions from Realm to verify whether the user's operations can be carried out Realm consider as
DataSource ;

1.4 , Shiro Architecture (internal)

  • Subject: any 'user' who can interact with the application;
  • Security Manager: equivalent to dispatcher servlet in spring MVC; It is the heart of Shiro. All specific interactions are controlled through security manager. It manages all subjects and is responsible for authentication, authorization, session and cache management.
  • Authenticator: responsible for Subject authentication. It is an extension point and can be customized; Authentication Strategy can be used, that is, when the user has passed the authentication;
  • Authorizer: authorizer, that is, access controller, which is used to determine whether the subject has permission to perform corresponding operations; That is, it controls the functions that users can access in the application;
  • Realm: there can be one or more realms, which can be considered as data sources of security entities, that is, those used to obtain security entities can be implemented in JDBC or memory, etc., which are provided by users; Therefore, we generally need to implement our own realm in applications
  • Session manager: a component that manages the session life cycle. Shiro can be used not only in the Web environment, but also in the ordinary Java se environment
  • CacheManager: cache controller to manage the cache of users, roles, permissions, etc; Because these data are rarely changed, the performance of access can be improved after being put into the cache;
  • Cryptography: password module. Shiro improves some common encryption components for password encryption, decryption, etc

First Shiro program

Shiro tutorial: 10 Minute Tutorial on Apache Shiro | Apache ShiroApache Shiro Tutorial | Apache Shiro10 Minute Tutorial on Apache Shiro | Apache Shiro 

hello-shrio

1.pom.xml

    <dependencies>
    <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-core -->
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>1.7.1</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.slf4j/jcl-over-slf4j -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
        <version>1.7.1</version>
        <scope>runtime</scope>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.1</version>
        <scope>runtime</scope>
    </dependency>

    <!-- https://mvnrepository.com/artifact/log4j/log4j -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
        <scope>runtime</scope>
    </dependency>
    </dependencies>

2. Write Shiro configuration

log4j.properties

log4j.rootLogger=INFO, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n

# General Apache libraries
log4j.logger.org.apache=WARN

# Spring
log4j.logger.org.springframework=WARN

# Default Shiro logging
log4j.logger.org.apache.shiro=INFO

# Disable verbose logging
log4j.logger.org.apache.shiro.util.ThreadContext=WARN
log4j.logger.org.apache.shiro.cache.ehcache.EhCache=WARN

shiro.ini

[users]
root = secret, admin
guest = guest, guest
presidentskroob = 12345, president
darkhelmet = ludicrousspeed, darklord, schwartz
lonestarr = vespa, goodguy, schwartz

# -----------------------------------------------------------------------------
# Roles with assigned permissions
# roleName = perm1, perm2, ..., permN
# -----------------------------------------------------------------------------
[roles]
admin = *
schwartz = lightsaber:*
goodguy = winnebago:drive:eagle5

3,Quickstart  

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * Simple Quickstart application showing how to use Shiro's API.
 *
 * @since 0.9 RC2
 */
public class Quickstart {

    //Use the log interface to use log output
    private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);


    public static void main(String[] args) {

        // The easy way to create a Shiro SecurityManager with configured
        // realms, users, roles and permissions is to use the simple INI config.     Domains, users, roles and permissions are configured using simple ini. Is to load Shiro Ini configuration file
        // We'll do that by using a factory that can ingest a .ini file and we read the configuration file by factory default
        // return a SecurityManager instance: returns a SecurityManager instance

        // Use the shiro.ini file at the root of the classpath Ini root directory is classpath
        // (file: and url: prefixes load from files and urls respectively):

        //                                                      Factory mode
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        SecurityManager securityManager = factory.getInstance();

        // for this simple example quickstart, make the SecurityManager / / for this simple quick start example, let SecurityManager
        // accessible as a JVM singleton.  Most applications wouldn't do this / / accessible JVM singletons. Most applications don't do that
        // and instead rely on their container configuration or web.xml for / / depends on their container configuration or web xml
        // webapps.  That is outside the scope of this simple quickstart, so        // webapps.   This is beyond the scope of a simple quick start, so
        // we'll just do the bare minimum so you can continue to get a feel
        // for things.                                                              // Right thing.
        SecurityUtils.setSecurityManager(securityManager);

        System.out.println("--------------Dead code above-----------------------");

        System.out.println("Core code");

        //Get the current user object Subject
        Subject currentUser = SecurityUtils.getSubject();

        //Get session from current user
        Session session = currentUser.getSession();
        session.setAttribute("someKey", "aValue");
        String value = (String) session.getAttribute("someKey");
        if (value.equals("aValue")) {
            log.info("Subject=> session [" + value + "]");
        }

        //Judge whether the user is authenticated
        if (!currentUser.isAuthenticated()) {
            //Token: a token is generated by account and password
            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
            token.setRememberMe(true);  //Set remember me

            try {
                currentUser.login(token);           //Execute force login operation~
            } catch (UnknownAccountException uae) {      //Unknown user name does not exist
                log.info("There is no user with username of " + token.getPrincipal());
            } catch (IncorrectCredentialsException ice) { //Wrong password
                log.info("Password for account " + token.getPrincipal() + " was incorrect!");
            } catch (LockedAccountException lae) {          //The user is locked, for example, 5 times, and the password is incorrect
                log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                        "Please contact your administrator to unlock it.");
            }
            // ... catch more exceptions here (maybe custom ones specific to your application?
            catch (AuthenticationException ae) {   //Authentication exception
                //unexpected condition?  error?
            }
        }

        //say who they are:
        //print their identifying principal (in this case, a username):
        log.info("User [" + currentUser.getPrincipal() + "] logged in successfully."); // Get the authentication access information of the current user

        //test a role:
        //Determine whether the user has a role
        if (currentUser.hasRole("schwartz")) {
            log.info("May the Schwartz be with you!");
        } else {
            log.info("Hello, mere mortal.");
        }

        //Coarse grain size
        //test a typed permission (not instance-level)
        if (currentUser.isPermitted("lightsaber:wield")) { //Check whether you have any permissions Shiro drive:eagle5 in ini
            log.info("You may use a lightsaber ring.  Use it wisely.");
        } else {
            log.info("Sorry, lightsaber rings are for schwartz masters only.");
        }

        //Fine grained
        //a (very powerful) Instance Level permission:
        if (currentUser.isPermitted("winnebago:drive:eagle5")) {  //Do you have higher permissions
            log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +
                    "Here are the keys - have fun!");
        } else {
            log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
        }

        //cancellation
        currentUser.logout();

        //end
        System.exit(0);
    }
}

Core:

//Get the current user object Subject
Subject currentUser = SecurityUtils.getSubject();
//Get session from current user
Session session = currentUser.getSession();
//Judge whether the user is authenticated
if (!currentUser.isAuthenticated()) { 


//Get the authentication access information of the current user
currentUser.getPrincipal() 
//Determine whether the user has a role
if (currentUser.hasRole("schwartz")) {
//Check whether you have any permissions
if (currentUser.isPermitted("lightsaber:wield")) { 
//Write off
currentUser.logout();

result:

Shiro integrated in SpringBoot

Environment construction

 1.pom.xml

        <!-- spring integration shiro -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.7.1</version>
        </dependency>

2.index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:shiro="https://www.thymeleaf.org/thymeleaf-extras-shiro">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>home page</h1>

<p th:text="${msg}"></p>


</body>
</html>

3.MyController

@Controller
public class MyController {

    @RequestMapping({"/", "/index"})
    public String toIndex(Model model) {
        model.addAttribute("msg", "Hello Shiro");
        return "index";
    }

}

4.ShiroConfig realm object needs to be customized

package com.gh.config;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Subject: user
 * SecurityManager: Manage all users
 * Realm: Connection data
 */
@Configuration
public class ShiroConfig {

    //3.ShiroFilterFactoryBean

     //2.DefaultWebSecurityManager

    //1. Creating a realm object requires customization

}

5.UserRealm

extends AuthorizingRealm   

//Customize userrealm extensions authoringrealm
public class UserRealm extends AuthorizingRealm {

    //to grant authorization
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("to grant authorization=======>principalCollection");


        return null;

    }

    //authentication
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("authentication======>authenticationToken");

        return null;

    }
}

6.ShiroConfig write backwards

package com.gh.config;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Subject: user
 * SecurityManager: Manage all users
 * Realm: Connection data
 */
@Configuration
public class ShiroConfig {

    //3.ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("webSecurityManager") DefaultWebSecurityManager webSecurityManager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //Set up security manager
        bean.setSecurityManager(webSecurityManager);

        return bean;
    }

     //2.DefaultWebSecurityManager
    @Bean(name = "webSecurityManager")   //Do not write default method name
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
        DefaultWebSecurityManager webSecurityManager = new DefaultWebSecurityManager();
        webSecurityManager.setRealm(userRealm);
        return webSecurityManager;
    }

    //1. Creating a realm object requires customization
    @Bean
    public UserRealm userRealm() { //userRealm1 is equivalent to an alias
        return new UserRealm();
    }

}

 7. Add page

add.html ,update.html simple page

controller 

    @RequestMapping("/user/toAdd")
    public String toAdd() {
        return "user/add";
    }

    @RequestMapping("/user/toUpdate")
    public String toUpdate() {
        return "user/update";
    }

index.html 

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:shiro="https://www.thymeleaf.org/thymeleaf-extras-shiro">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>home page</h1>


<p th:text="${msg}"></p>

<a th:href="@{/user/toAdd}">newly added</a>

<a th:href="@{/user/toAdd}">newly added</a>

</body>
</html>

8. Test

User interception

Intercept:
        ShiroConfig--ShiroFilterFactoryBean

        //Add shiro's built-in interceptor
        /**
         * anon: Access without authentication
         * authc: Authentication is required to access
         * user: You must have the 'remember me' function to access
         * perms: You must have permission to access a resource
         * role: You must have a role permission to access
         */

        //LinkedHashMap is generally used for chain
        Map<String, String> filterMap = new LinkedHashMap<>();

        //to grant authorization
      filterMap.put("/user/toAdd","authc");
      filterMap.put("/user/toUpdate","authc");
      //Support wildcards
//      filterMap.put("/user/*","authc");

        bean.setFilterChainDefinitionMap(filterMap);
Map<String, String> filterMap = new LinkedHashMap<>();
filterMap.put("/user/*","authc");
bean.setFilterChainDefinitionMap(filterMap);

Interception succeeded

Jump to login page

login.html,controller

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Login page</title>
</head>

<form method="get" th:action="@{/login}">
    <p>
        user name:<input type="text" name="username"/>
    </p>
    <p>
        password:<input type="password" name="password"/>
    </p>
    <input type="submit" value="Sign in"/>
</form>
</body>
</html>
    @RequestMapping("/toLogin")
    public String toLogin() {
        return "login";
    }

ShiroConfig--ShiroFilterFactoryBean

//Set login request
bean.setLoginUrl("/toLogin");

Shrio uses user authentication

1, MyController
@RequestMapping("/login")
public String login(String username, String password, Model model) {

    System.out.println("===========>"+username);
    System.out.println("===========>"+password);

    //Get current user subject
    Subject user = SecurityUtils.getSubject();

    //Encapsulate the user's login data token token
    UsernamePasswordToken token = new UsernamePasswordToken(username, password);

    try {
        user.login(token);//The login method executed. If there is no exception, it indicates that it is OK
        return "index";
    } catch (UnknownAccountException e) {
        //User name error
        model.addAttribute("msg","User name error!!!");
        return "login";
    }catch (IncorrectCredentialsException e){
        //Password error
        model.addAttribute("msg","Password error!!!");
        return "login";
    }

}

Execution: entered the authentication method

II. Certification:

UserRealm
    //authentication
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("authentication======>authenticationToken");


        UsernamePasswordToken userToken = (UsernamePasswordToken) token;//The login information can be obtained by converting the fixed routine into the Token we know

        //Assume that the user name and password are retrieved from the database
        String username = "root";
        String password = "123456";

        if (!userToken.getUsername().equals(username)){
            return null;//Throw an exception UnknownAccountException
        }

        /*
        Three parameters
                Obtain the authentication of the current user 
                User password  
                Authentication name
        */   
        return new SimpleAuthenticationInfo("",password, "");

    }

Shrio integrates Mybatis

1.pom.xml

        <!-- mysql Database connection dependency -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!-- log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <!-- druid data source -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>

        <!-- mybatis-springboot -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>

2.application.yml 

# Application service WEB access port
server:
  port: 8080

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    name: defaultDataSource
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/mapper?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
    type: com.alibaba.druid.pool.DruidDataSource

    #Spring Boot does not inject these attribute values by default and needs to bind by itself
    #druid data source proprietary configuration
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true

    #Configure filters for monitoring statistics interception, stat: monitoring statistics, log4j: logging, wall: defensive sql injection
    #If allowed, an error will be reported in Java lang.ClassNotFoundException: org. apache. log4j. Priority
    #Then import log4j dependency. Maven address: https://mvnrepository.com/artifact/log4j/log4j
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

3.pojo

        user

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    private Integer id;
    private String name;
    private String pwd;
}

4.dao

        UserDao

@Repository
@Mapper
public interface UserDao {
    /**
     *  Sign in
     * @param name
     * @return
     */
    User queryUserByName(String name);
}

        UserMapper

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gh.dao.UserDao">
    <select id="queryUserByName" resultType="com.gh.pojo.User" parameterType="String">
        SELECT * FROM `user` WHERE `name` = #{name}
    </select>
</mapper>

5.service

        UserService

public interface UserService {
    /**
     *  Sign in
     * @param name
     * @return
     */
    User queryUserByName(String name);
}

        UserServiceImpl

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    public User queryUserByName(String name) {
        return userDao.queryUserByName(name);
    }
}

Test: application tests

@SpringBootTest
class ApplicationTests {


    @Autowired
    UserServiceImpl userService;

    @Test
    void contextLoads() {
        System.out.println(userService.queryUserByName("Big white"));
    }

}

 6.UserRealm get data from database

//Customize userrealm extensions authoringrealm
public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    //to grant authorization
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("to grant authorization=======>principalCollection");

        return null;


    }

    //authentication
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("authentication======>authenticationToken");


        UsernamePasswordToken userToken = (UsernamePasswordToken) token;//We can get the regular login information


        //Connect to real database
        User user = userService.queryUserByName(userToken.getUsername());

        //Determine whether the user exists
        if (user == null) { //There is no such person
            return null;        //Throw UnknownAccountException
        }

        //Log in successfully and store user information in session
        Subject currentUser = SecurityUtils.getSubject();

        currentUser.getSession().setAttribute("user",currentUser);


        /*
        Three parameters
                Obtain the authentication of the current user
                User password
                Authentication name
        */
        //Password authentication shrio~ is encrypted
        return new SimpleAuthenticationInfo("",user.getPwd(), "");

    }
}

Authorization

1. Authorize ShiroConfig--ShiroFilterFactoryBean

        //Resource permissions
        filterMap.put("/user/toAdd","perms[user:add]"); // Only users with user: add can access / user/toAdd
        filterMap.put("/user/toUpdate", "perms[user:update]");

 2.noAuth.html # unauthorized page

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1 style="color: red">
    Sorry, you don't have permission to access this resource!!!
</h1>
</body>
</html>

3. Set unauthorized requests

ShiroConfig--ShiroFilterFactoryBean

bean.setUnauthorizedUrl("/noAuth");

 4. to grant authorization

    //to grant authorization
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("to grant authorization=======>principalCollection");

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addStringPermission("user:add");
       
        return info;


    }

 5. Get authorization from database

Add a database perms field to the user table

    //to grant authorization
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("to grant authorization=======>principalCollection");

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addStringPermission("user:add");

        //Get the currently logged in object
        Subject subject = SecurityUtils.getSubject();
        User currentUser = (User) subject.getPrincipal();  //Get User object

        //Set the permissions of the current user
        info.addStringPermission(currentUser.getPerms());

        return info;

    }

Note: authentication binding is required

Permission selection

pom.xml

<!-- shiro-thymeleaf -->
<dependency>
    <groupId>com.github.theborakompanioni</groupId>
    <artifactId>thymeleaf-extras-shiro</artifactId>
    <version>2.0.0</version>
</dependency>

Configuration required: ShiroConfig can be used

    //Shirodialect Shiro integrated thymeleaf
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }

index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:shiro="https://www.thymeleaf.org/thymeleaf-extras-shiro">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>home page</h1>

<!--from session Judgment value-->
<div th:if="${session.loginUser}==null">
    <a th:href="@{/toLogin}">Sign in</a>
</div>

<p th:text="${msg}"></p>


<div shiro:hasPermission="user:add">  <!--hasPermission Do you have this permission-->
    <a th:href="@{/user/toAdd}">newly added</a>
</div>

<div shiro:hasPermission="user:update">
    <a th:href="@{/user/toUpdate}">modify</a>
</div>


</body>
</html>

Login succeeded in obtaining session

UserRealm / / authentication in progress

//Log in successfully and store user information in session 
Subject currentSubject = SecurityUtils.getSubject(); 
Session session = currentSubject.getSession(); 
session.setAttribute("loginUser",currentUser);

Catalogue

ShiroConfig

package com.gh.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Subject: user
 * SecurityManager: Manage all users
 * Realm: Connection data
 */
@Configuration
public class ShiroConfig {

    //3.ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("webSecurityManager") DefaultWebSecurityManager webSecurityManager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //Set up security manager
        bean.setSecurityManager(webSecurityManager);


        //Add shiro's built-in interceptor
        /**
         * anon: Access without authentication
         * authc: Authentication is required to access
         * user: You must have the 'remember me' function to access
         * perms: You must have permission to access a resource
         * role: You must have a role permission to access
         */

        //LinkedHashMap is generally used for chain
        Map<String, String> filterMap = new LinkedHashMap<>();

        //to grant authorization
        filterMap.put("/user/toAdd","authc");
        filterMap.put("/user/toUpdate","authc");


      //Support wildcards
//      filterMap.put("/user/*","authc");

        //Under normal resource permissions, unauthorized resources will jump to the unauthorized page
        filterMap.put("/user/toAdd","perms[user:add]"); // Only users with user: add can access / user/toAdd
        filterMap.put("/user/toUpdate","perms[user:update]");

        bean.setFilterChainDefinitionMap(filterMap);

        //Set login request
        bean.setLoginUrl("/toLogin");

        //Set unauthorized requests
        bean.setUnauthorizedUrl("/noAuth");

        return bean;
    }

     //2.DefaultWebSecurityManager
    @Bean(name = "webSecurityManager")   //Do not write default method name
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
        DefaultWebSecurityManager webSecurityManager = new DefaultWebSecurityManager();
        webSecurityManager.setRealm(userRealm);
        return webSecurityManager;
    }

    //1. Creating a realm object requires customization
    @Bean
    public UserRealm userRealm() { //userRealm1 is equivalent to an alias
        return new UserRealm();
    }


    //Shirodialect Shiro integrated thymeleaf
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }


}

UserRealm

package com.gh.config;

import com.gh.pojo.User;
import com.gh.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

//Customize userrealm extensions authoringrealm
public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    //to grant authorization
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("to grant authorization=======>principalCollection");

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addStringPermission("user:add");

        //Get the currently logged in object
        Subject subject = SecurityUtils.getSubject();
        User currentUser = (User) subject.getPrincipal();  //Get User object

        //Set the permissions of the current user
        info.addStringPermission(currentUser.getPerms());

        return info;

    }

    //authentication
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("authentication======>authenticationToken");

        UsernamePasswordToken userToken = (UsernamePasswordToken) token;//The login information can be obtained by converting the fixed routine into the Token we know

        //Connect to real database
        User user = userService.queryUserByName(userToken.getUsername());

        //Determine whether the user exists
        if (user == null) { //There is no such person
            return null;        //Throw UnknownAccountException
        }


        //Log in successfully and store user information in session
        Subject currentSubject = SecurityUtils.getSubject();

        Session session = currentSubject.getSession();
        session.setAttribute("loginUser",user);

        /*
        Three parameters
                Obtain the authentication of the current user
                User password
                Authentication name
        */
        //Password authentication shrio~ is encrypted
        return new SimpleAuthenticationInfo(user,user.getPwd(), "");

    }
}

MyController

package com.gh.controller;


import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class MyController {

    @RequestMapping({"/", "/index"})
    public String toIndex(Model model) {
        model.addAttribute("msg", "Hello Shiro");
        return "index";
    }

    @RequestMapping("/user/toAdd")
    public String toAdd() {
        return "user/add";
    }

    @RequestMapping("/user/toUpdate")
    public String toUpdate() {
        return "user/update";
    }

    @RequestMapping("/toLogin")
    public String toLogin() {
        return "login";
    }

    @RequestMapping("/login")
    public String login(String username, String password, Model model) {

        System.out.println("===========>"+username);
        System.out.println("===========>"+password);

        //Get current user subject
        Subject user = SecurityUtils.getSubject();

        //Encapsulate the user's login data token token
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);

        try {
            user.login(token);//The login method executed. If there is no exception, it indicates that it is OK
            return "index";
        } catch (UnknownAccountException e) {
            //User name error
            model.addAttribute("msg","User name error!!!");
            return "login";
        }catch (IncorrectCredentialsException e){
            //Password error
            model.addAttribute("msg","Password error!!!");
            return "login";
        }

    }

    @RequestMapping("/noAuth")
    public String author(){
        return "noAuth";
    }
}

 

Topics: Java Spring Boot security