Shiro

Shiro profile

Shiro is what?

  • Apache Shiro is a JavaSecurity (permissions) framework.
  • Shiro can easily develop applications that are good enough to be used in both JavaSE and JavaEE environments.
  • Shiro can do it,certification.authorization.encryption.Session management.Web integration.The cacheAnd so on.
  • Liverpoolfc.tv: shiro.apache.org/
  • Official documentation 10 minutes quick Start: shiro.apache.org/10-minute-t…
  • Download :github.com/apache/shir…

Shiro’s three main functions

Shiro has three core components, Subject, SecurityManager, and Realm

  • Subject: indicates the authentication Subject. The object with which the application code interacts directly is Subject, which represents the current user. The Principals and Credentials are included.

  • SecurityManager: indicates the security administrator. Is the core of Shiro’s architecture. All interactions with the Subject are delegated to the SecurityManager, the Subject is the facade, and the SecurityManager is the real performer. It is responsible for interacting with Shiro’s other components.

  • Realm: Is a Realm. Acts as a “bridge” between Shiro and application security data. Shiro obtains security data (such as users, roles, and permissions) from a Realm. To authenticate users, The SecurityManager needs to obtain the corresponding users from a Realm for comparison to determine whether they are legitimate. You need to obtain user roles and permissions from the Realm to verify that user operations can be performed. You can view the Realm as a DataSource.

  • Authentication: identity authentication, login, verify whether the user has the corresponding identity;
  • Authorization: Authorization, namely, permission verification, verifies whether an authenticated user has a certain permission, that is, determines whether the user can perform operations, for example, verify whether a user has a role, or verify whether a user has a certain permission on a resource in a fine-grained manner.
  • Session Manager: Session management, that is, after the user logs in, it is the second session. All the information about it is in the session before the user logs out. The session can be a normal JavaSE environment or a Web environment;
  • CryptographyEncryption: Protects the security of data. For example, passwords are encrypted and stored in a database rather than in plain text.
  • Web Support: Web support, can be very easy integration into the Web environment;
  • Caching: Cache. For example, after a user logs in, the user information, roles, and permissions do not need to be checked every time, which improves efficiency
  • ConcurrencyShiro supports concurrent validation in multi-threaded applications, which means that permissions can be automatically propagated, for example by starting another thread in one thread
  • Testing: Provide test support;
  • RunAsAllow one user to pretend to be another user (if they allow it).
  • Remember Me: Remember me, this is a very common feature, which means that once you log in, you don’t need to log in the next time

Shiro Architecture (External)

Shiro from the outside, that is, from an application perspective, see how Shiro gets things done: Subject user, SecurityManager manages all user Realm connection data

  • subject: The object of direct interaction of application code is Subject, that is to say, Shiro’s external API core is Subject, Subject represents the current user, the user is not necessarily a specific person, anything interacting with the current application is Subject, such as web crawler, robot, etc. All interactions with the Subject are delegated to the SecurityManager; The Subject is a facade, and the SecurityManager is the actual performer.

  • SecurityManager: The security manager, that is, all security-related operations interact with SercurityManager, and it manages all subjects. As you can see, it is the core of Shiro and is responsible for interacting with Shiro’s other components. It corresponds to the role of SpringMVC’s DispatcherServlet

  • Realm: Shiro obtains security data from realms (such as users, roles, and permissions). The SecurityManager needs to authenticate users from realms to determine whether their identities are valid. We need to get the user’s role and permission from Realm to verify whether the user’s operation can be performed.

Shiro Architecture (internal)

  • Subject: Any user who can interact with the application;
  • Security Manager: equivalent to SpringMVCDispatcherSerlet; Shiro isThe heartAll concrete interactions pass throughSecurity ManagerIt manages all subjects and is responsible for authentication, authorization, session, and cache management.
  • Authenticator: be responsible forSubjectAuthentication, is – an extension point that can be customized for implementation; You can useAuthentication strategy(Authentication Strategy), that is, under what circumstances is the user authenticated;
  • Authorizer: authorizer, that is, access controller, used to determine whether the principal has permission to perform the corresponding operation; It controls the user’s access to the application

Those functions of;

  • RealmCan have – one or more realms, which can be thought of as secure entity data sources for obtaining secure entities, can be implemented using JDBC, can be implemented in memory, and so on, provided by the user; So all applications need to implement their own realm
  • SessionManager: a component that manages the Session lifecycle, and Shiro can be used not only in Web environments, but also in normal JavaSE environments
  • CacheManager: cache controller to manage caches such as users, roles, permissions, etc. Because this data rarely changes, caching can improve access performance;
  • Cryptography: Password module, Shiro enhances some common encryption components for password encryption, decryption, etc

Shiro Quick start

The preparatory work

Download: GitHub resource

Create a normal Maven project, Springboot-08-shiro, and delete the SRC directory and the useless files

Create a new SpringMVC project hello_shiro in Springboot-08-shiroFind the file pom.xmlGithub.com/apache/shir…

Copy dependencies in POM.xml

    <dependencies>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
        </dependency>

        <! -- configure logging -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <scope>runtime</scope>
        </dependency>
          <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-nop</artifactId>
        </dependency>
    </dependencies>
Copy the code

Change add version number:

    <dependencies>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.7.1</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>1.7.30</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.30</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>
Copy the code

copyGithub.com/apache/shir… 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
Copy the code

Download the plug-in and restart IDEA

shiro.ini

[users]
# user 'root' with password 'secret' and the 'admin' role
root = secret, admin
# user 'guest' with the password 'guest' and the 'guest' role
guest = guest, guest
# user 'presidentskroob' with password '12345' ("That's the same combination on
# my luggage!!!";) ), and role'president'
presidentskroob = 12345, president
# user 'darkhelmet' with password 'ludicrousspeed' and roles 'darklord' and 'schwartz'
darkhelmet = ludicrousspeed, darklord, schwartz
# user 'lonestarr' with password 'vespa' and roles 'goodguy' and 'schwartz'
lonestarr = vespa, goodguy, schwartz

# -----------------------------------------------------------------------------
# Roles with assigned permissions
# 
# Each line conforms to the format defined in the
# org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions JavaDoc
# -----------------------------------------------------------------------------
[roles]
# 'admin' role has all permissions, indicated by the wildcard The '*'
admin = *
# The 'schwartz' role can do anything (*) with any lightsaber:
schwartz = lightsaber:*
# The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with
# license plate 'eagle5' (instance specific id)
goodguy = winnebago:drive:eagle5
Copy the code

Continue copying:Github.com/apache/shir… Quickstart.java

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;

import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class Quickstart {
    // Use log output
    private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);


    public static void main(String[] args) {

        DefaultSecurityManager securityManager = new DefaultSecurityManager();
        IniRealm iniRealm = new IniRealm("classpath:shiro.ini");
        securityManager.setRealm(iniRealm);


        SecurityUtils.setSecurityManager(securityManager);

        // Now that a simple Shiro environment is set up, let's see what you can do:
        // Now that you have set up a simple Shiro environment, let's see what you can do:

        // get the currently executing user:
        // Get the currently executing user: getSubject
        Subject currentUser = SecurityUtils.getSubject();

        // Get Session from the current user
        Session session = currentUser.getSession();

        session.setAttribute("someKey"."aValue");

        String value = (String) session.getAttribute("someKey");
        if (value.equals("aValue")) {
            log.info("Securit=>Session! [" + value + "]");
        }

        // If indicates whether the current user is authenticated
        if(! currentUser.isAuthenticated()) {// If the authentication succeeds, get the account password and generate a Token
            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr"."vespa");
            // Set remember me
            token.setRememberMe(true);
            try {
                // Login operation performed!
                currentUser.login(token);
            } catch (UnknownAccountException uae) { // Unknown account
                log.info("There is no user with username of " + token.getPrincipal());
            } catch (IncorrectCredentialsException ice) {// The password is not normal, then output
                log.info("Password for account " + token.getPrincipal() + " was incorrect!");
            } catch (LockedAccountException lae) {// The user is locked. For example, the account is locked after five failed attempts
                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) {
                //unexpected condition? error?}}// Get the verification code of the current user
        log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");

        // Test roles, such as vip1, vip2
        if (currentUser.hasRole("schwartz")) {
            log.info("May the Schwartz be with you!");
        } else {
            log.info("Hello, mere mortal.");
        }

        // Check if there are any permissions, coarse-grained!
        if (currentUser.isPermitted("lightsaber:wield")) {
            log.info("You may use a lightsaber ring. Use it wisely.");
        } else {
            // If all options are not met, output
            log.info("Sorry, lightsaber rings are for schwartz masters only.");
        }

        // Whether to have more advanced permissions, fine granularity!
        if (currentUser.isPermitted("winnebago:drive:eagle5")) {
            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!");
        }

        / / logout
        currentUser.logout();
        // End the system
        System.exit(0); }}Copy the code

Start the test



SpringBoot integrates Shiro environment setup

1. Create a SpringBoot project

To create the SpringBoot project shiro-Springboot, select Web and Thymeleaf

2. Create index.html under Templates

<! DOCTYPEhtml>
<html lang="en" xmlns:th="https://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>
Copy the code

3. Create myController.java under the Controller package

@Controller
public class MyController {

    @RequestMapping({"/","/index"})
    public String index(Model model){
        model.addAttribute("msg"."hello,Shiro");
        return "index"; }}Copy the code

Start test:

4. Three functions, basic understanding

Subject: user SecurityManager: manages all user Realm: connection data


5. Import the JAR package

<! --shiro--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.41.</version>
        </dependency>
Copy the code

6. Write ShiroConfig and UserRealm

public class UserRealm extends AuthorizingRealm {
    / / authorization
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("Authorized doGetAuthorizationInfo performed =");
        return null;
    }
    
    / / certification
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("Executed =" Authenticated doGetAuthenticationInfo");
        return null; }}Copy the code
@Controller
public class ShiroConfig {
    // Three core elements:

    //ShiroFilterFactoryBean
    // Step 3:
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        // Set the security manager
        bean.setSecurityManager(defaultWebSecurityManager);
        return bean;
    }

    //DafaultWebSecurityManager
    // Step 2:
    @Bean(name="securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        / / associated UserRealm
        securityManager.setRealm(userRealm);
        return securityManager;
    }


    // Create a Realm object that requires a custom class
    // Step 1:
    @Bean
    public UserRealm userRealm(a){
        return newUserRealm(); }}Copy the code

7. Write HTML pages

Create the user directory in the Templates directory to write the HTML pages, add.html, update.html

<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>add</title>
</head>
<body>
<h1>add</h1>
</body>
</html>
Copy the code
<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>update</title>
</head>
<body>
<h1>update</h1>
</body>
</html>
Copy the code

8. Modify MyController to add response request

@Controller
public class MyController {

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

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

    @RequestMapping("/user/update")
    public String update( ){
        return "user/update"; }}Copy the code

9. Modify the Index home page

<! DOCTYPE html> <html lang="en" xmlns:th="https://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>
<br/><hr>

<a th:href="@{/user/add}">add</a>
<a th:href="@{/user/update}">update</a>
</body>
</html>
Copy the code

10. Final test

Shiro implements login interception

1. Create a login page

<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>The login</title>
</head>
<body>

<h1 align="center">The login</h1>
<hr>
<form action="">
      <p align="center">User name:<input type="text" name="username"></p>
      <p align="center">The secret code:<input type="text" name="password"></p>
      <p align="center"><input type="submit"></p>
</form>

</body>
</html>
Copy the code

2. Add jump to MyController

    @RequestMapping("/toLogin")
    public String toLogin(a){
        return "login";
    }
Copy the code

Add Shiro’s built-in filters

Authc: Authc must be authenticated. User: Must have, remember me function, to access perms: You can access perms only when you have the permission on a resource role: you can access perms only when you have the permission on a role

@Controller
public class ShiroConfig {
    // Three core elements:

    //ShiroFilterFactoryBean
    // Step 3:
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        // Set the security manager
        bean.setSecurityManager(defaultWebSecurityManager);

        Add Shiro's built-in filters
        /* Anon: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC

        // Set login permission to block login
        Map<String, String> filterMap = new LinkedHashMap<>();
        //filterMap.put("/user/add", "authc");
        //filterMap.put("/user/update", "authc");
        filterMap.put("/user/*"."authc");
        
        bean.setFilterChainDefinitionMap(filterMap);

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

        return bean;
    }


    //DafaultWebSecurityManager
    // Create a Realm object that requires a custom class.Copy the code

4. Start test:

We can see it’s been intercepted!



Shiro implements user authentication

1. Write certifications

    @RequestMapping("/login")
    public String login(String username,String password,Model model){
        // Get the current user
        Subject subject = SecurityUtils.getSubject();
        // Encapsulate user login data
        // Encapsulate as a Token
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);

        try {
            // Verify the login, if there are no exceptions, it is successful
            subject.login(token);
            return "index";
        }catch (UnknownAccountException e){// The user name does not exist
            model.addAttribute("msg"."User name error");
            return "login";
        }catch (IncorrectCredentialsException e){
            model.addAttribute("msg"."Password error");
            return "login"; }}Copy the code

2. Add a redirect and error message to login

<p align="center" th:text="${msg}" style="color: red"></p>
<form th:action="@{/login}">
      <p align="center">User name:<input type="text" name="username"></p>
      <p align="center">The secret code:<input type="text" name="password"></p>
      <p align="center"><input type="submit"></p>
</form>
Copy the code

3. Determine the authentication

 / / certification
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("Executed =" Authenticated doGetAuthenticationInfo");

        // The user name is obtained from the password data
        String name="qingfeng";
        String password="123456";

        // Create a token
        UsernamePasswordToken  usertoken = (UsernamePasswordToken) token;

        // Determine the incoming data
        if(! usertoken.getUsername().equals(name)){return null;// UnknownAccountException was thrown
        }
        // Password authentication, shiro does
        return new SimpleAuthenticationInfo("",password,"");
    }
Copy the code

4. Test:

Password mistakeUser name errorLogin successful

Shiro integration mybatis

1. Import the SQL JAR package

<! --MySQL--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.022.</version> </dependency> <! --log4j--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.217.</version> </dependency> <! --druid--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2. 5</version> </dependency> <! --mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.14.</version>
        </dependency>
Copy the code

2. Write application. Yml

spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/mybatis? useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UT C
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource

    #Spring Boot does not inject these property values by default, you need to bind them yourself
    #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 to monitor statistics interception, stat: monitor statistics, log4j: logging, wall: defend against SQL injection
    # if allowed times wrong Java. Lang. ClassNotFoundException: org.. Apache log4j. Priority
    # import log4j dependence can, 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
    
mybatis:
  type-aliases-package: com.cy.pojo
  mapper-locations: classpath:mapper/*.xml
Copy the code

3. Write entity class User,

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private int id;
    private String name;
    private String pwd;
    private String perms;
}

Copy the code

4. Write UserMapper interface

@RequestMapping
@Mapper// This annotation indicates that this is a Mybatis mapper class
public interface UserMapper {

    User queryUserByName(String name);
}
Copy the code

5. Create UserMapper. XML

Create the mapper directory usermapper.xml under the resource package

UserMapper.xml


      
<! DOCTYPEmapper
        PUBLIC "- / / mybatis.org//DTD Mapper / 3.0 / EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.cy.mapper.UserMapper">

    <select id="queryUserList"  resultType="User">
        select * from user;
    </select>

    <select id="queryUserByName" resultType="User" parameterType="String">
        select * from user where name=#{name}
    </select>

</mapper>
Copy the code

6. The service layer

UserService interface

package com.cy.service;

import com.cy.pojo.User;

public interface UserService {
    public User queryUserByName(String name);
}
Copy the code

UserServiceImpl

package com.cy.service;

import com.cy.mapper.UserMapper;
import com.cy.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService{
    @Autowired
    UserMapper userMapper;

    @Override
    public User queryUserByName(String name) {
        returnuserMapper.queryUserByName(name); }}Copy the code

7. Test

Tested ShiroSpringbootApplicationTests

@SpringBootTest
class ShiroSpringbootApplicationTests {
    @Autowired
    UserServiceImpl userService;

    @Test
    void contextLoads(a) {
        System.out.println(userService.queryUserByName("The wind")); }}Copy the code

8. Modify the previous user authentication

Connect to a real database for user authentication

public class UserRealm extends AuthorizingRealm {

    @Autowired
    UserService userService;

    / / authorization
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("Authorized doGetAuthorizationInfo performed =");
        return null;
    }
    
    / / certification
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("Executed =" Authenticated doGetAuthenticationInfo");

        // Create a token
        UsernamePasswordToken  usertoken = (UsernamePasswordToken) token;
        // Connect to a real database
        User user = userService.queryUserByName(usertoken.getUsername());

        if(user==null) {// The account was not found
            return null;
        }
        // You can use encrypted MD5, MD5 appearance level encryption
        // Password authentication, shiro does
        return new SimpleAuthenticationInfo("",user.getPwd(),""); }}Copy the code

Shiro requests authorization implementations

1. Configure authorization in ShiroConfig

  // Set login permission to block login
        Map<String, String> filterMap = new LinkedHashMap<>();

        // Authorization, normally, the page without authorization will be redirected to the unauthorized page
        filterMap.put("/user/add"."perms[user:add]");
        filterMap.put("/user/update"."perms[user:update]");
        
        filterMap.put("/user/*"."authc");
        bean.setFilterChainDefinitionMap(filterMap);
        // Set the login request
        bean.setLoginUrl("/toLogin");
        // Unauthorized page
        bean.setUnauthorizedUrl("/noauth");
        
        return bean;
Copy the code

2. Set up a blocking page

    @ResponseBody
    @RequestMapping("/noauth")
    public String unauthorized(a){
        return "This page cannot be accessed without authorization";
    }
Copy the code

3. Start the test

4. Authorize the user

UserRealm.java

    / / authorization
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("Authorized doGetAuthorizationInfo performed =");
        // Note the distinction between SimpleAuthenticationInfo and SimpleAuthorizationInfo
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
       // info.addStringPermission("user:add");

        // Get the object currently logged in
        Subject subject = SecurityUtils.getSubject();
        // Cast to User
        User currentUser = (User) subject.getPrincipal();// Get the User object
        
        // Set the permissions of the current user
        info.addStringPermission(currentUser.getPerms());

        return info;
    }
Copy the code

Testing: We can see that authorization was successful

However, we found a problem that all users in the database can access it freely, so we should assign permissions to the database

5. Add a column to the user table

Binding authority


Shiro integration Thymeleaf

1. Import the JAR package

        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>
Copy the code
  • The code

Structure directory:

2. Configure the config

ShiroConfig

    ShiroDialect: used to integrate Shiro Thymeleaf
    @Bean
    public ShiroDialect getShiroDialect(a){
        return new ShiroDialect();
    }
Copy the code

3. Modify the index. HTML

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

<h1 align="center"Word-wrap: break-word! Important; "> <div align="center" th:if="${session.loginUser==null}">
    <a th:href="@{/toLogin}"< div style = "box-sizing: border-box! Important; word-wrap: break-word! Important;"center" th:text="${msg}"></p>
<br/><hr>


<div align="center" Shiro:hasPermission="user:add">

<a th:href="@{/user/add}">add</a>
</div>

<div align="center" Shiro:hasPermission="user:update">
<a th:href="@{/user/update}">update</a>
</div>

</body>
</html>
Copy the code
   / / certification
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("Executed =" Authenticated doGetAuthenticationInfo");

        // Create a token
        // The user name and password are obtained from the database
        UsernamePasswordToken  usertoken = (UsernamePasswordToken) token;
        // Connect to a real database
        User user = userService.queryUserByName(usertoken.getUsername());// Get the user name


        if(user==null) {// The account was not found
            return null;
        }

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

        // Password authentication, shiro does
        return new SimpleAuthenticationInfo("",user.getPwd(),"");
    }
Copy the code