Super detailed, with source code! SpringBoot+shiro+mybatis+Thymeleaf realize permission login

Recently, I was working on a final project, which is to use ssm+thymeleaf+vue+shiro to complete a project that has permission to log in and can add, delete, check and modify user information. The following is just to realize permission authentication and login. The reason why I chose shiro over spring Security is that I tried. Security is really difficult and the encapsulation is too powerful. Hahaha, so I decided to give up and choose shiro.

The next article also implements the addition, deletion, query and modification, using vue, but there is no separation between the front and rear ends, Blog link

! github source code connection , please download it yourself.

Tip: this project has been added, deleted, checked and modified. If you follow the following blog, you can also make page Jump permission, but there is no addition, deletion, check and modification.

Here is a Demo for learning shiro:

1. First, the underlying database:

-- ----------------------------
-- Table structure for role
-- ----------------------------
CREATE TABLE `role`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Role table primary key',
  `role_name` varchar(32) DEFAULT NULL COMMENT 'Role name',
  PRIMARY KEY (`id`)
);

-- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO `role` VALUES (1, 'SUPER_ADMIN');
INSERT INTO `role` VALUES (2, 'ADMIN');
INSERT INTO `role` VALUES (3, 'USER');

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'User primary key',
  `username` varchar(32) NOT NULL COMMENT 'user name',
  `password` varchar(32) NOT NULL COMMENT 'password',
  `role_id` int(11) DEFAULT NULL COMMENT 'And role Foreign key associated with role table',
  PRIMARY KEY (`id`),
  CONSTRAINT `user_role_on_role_id` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`)
);

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'BWH_Steven', '666666', 1);
INSERT INTO `user` VALUES (2, 'admin', '666666', 2);
INSERT INTO `user` VALUES (3, 'zhangsan', '666666', 3);

-- ----------------------------
-- Table structure for permission
-- ----------------------------
CREATE TABLE `permission`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Permission table primary key',
  `permission_name` varchar(50) NOT NULL COMMENT 'Permission name',
  `role_id` int(11) DEFAULT NULL COMMENT 'And role Foreign key associated with role table',
  PRIMARY KEY (`id`),
  CONSTRAINT `permission_role_on_role_id` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`)
);

-- ----------------------------
-- Records of permission
-- ----------------------------
INSERT INTO `permission` VALUES (1, 'user:*', 1);
INSERT INTO `permission` VALUES (2, 'user:*', 2);
INSERT INTO `permission` VALUES (3, 'user:queryAll', 3);

2. Create a spring boot project and build it with maven

Create entity classes (User, Role, Permissions):
User:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String username;
    private String password;
    //Role set corresponding to user
    private Role role;
}

Role:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Role {
    private Integer id;
    private String roleName;


}

Permissions:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Permissions {
    private Integer id;
    private String permissionName;
    private Role role;
}

We need to know the relationship between the three entity classes, User and Role one-to-one, Role and Permissions one-to-one. Of course, we can also write them all as many to many, which requires changing the database file and entity class.

3. In POM Add dependency to XML:

Only relevant dependency sources are given below

<dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.5.3</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

4. Integrate mybatis and springboot:

You only need to create a dao layer and a service layer. You need to remember to add annotations:
(1)mapper configuration file (you can also use annotation form):

<?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.example.csy.dao.UserMapper">

    <select id="queryUserByUsername" resultMap="userRoleMap">
        SELECT u.*,r.role_name FROM `user` u, `role` r
          WHERE username = #{username} AND u.role_id = r.id;
    </select>
    <!-- Encapsulation definition User and role of resultMap -->
    <resultMap id="userRoleMap" type="com.example.csy.entity.User">
        <id property="id" column="id"/>
        <result property="username" column="username"></result>
        <result property="password" column="password"></result>
        <!-- Configuration encapsulation UserPojo Content of -->
        <association property="role" javaType="com.example.csy.entity.Role">
            <id property="id" column="id"></id>
            <result property="roleName" column="role_name"></result>
        </association>
    </resultMap>


    <select id="queryPermissionByUsername" resultMap="permissionRoleMap">
        SELECT p.* ,r.role_name FROM `user` u, `role` r, `permission` p
          WHERE username = #{username} AND u.role_id = r.id AND p.role_id = r.id;
    </select>
    <!-- Encapsulation definition permission and role of resultMap -->
    <resultMap id="permissionRoleMap" type="com.example.csy.entity.Permissions">
        <id property="id" column="id"/>
        <result property="permissionName" column="permission_name"></result>
        <!-- Configuration encapsulation Role Content of -->
        <association property="role" javaType="com.example.csy.entity.Role">
            <id property="id" column="id"></id>
            <!--property Is the parameter name assigned in the entity class, column Is the column name of the database-->
            <result property="roleName" column="role_name"></result>
        </association>
    </resultMap>
</mapper>

(2) DAO layer:

@Mapper
public interface UserMapper {
    User queryUserByUsername(@Param("username") String username);

    Permissions queryPermissionByUsername(@Param("username") String username);
}

(3) service layer:

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

    @Override
    public User queryUserByUsername(String username) {

        return userMapper.queryUserByUsername(username);
    }

    @Override
    public Permissions queryPermissionByUsername(String username) {
        return userMapper.queryPermissionByUsername(username);
    }
}

Here, our integration of mybatis+springboot is basically over, so test it in the test class:

@SpringBootTest
class CsyApplicationTests {

    @Autowired
    private UserMapper userMapper;

    @Test
    void contextLoads() {
        User admin = userMapper.queryUserByUsername("admin");
        System.out.println(admin.toString());
        Permissions permission = userMapper.queryPermissionByUsername("admin");
        System.out.println(permission.toString());
    }
}

Test results:
The query results are obtained

6. Integrate Thymeleaf:

Front page:
On the html page, we integrate Thymeleaf, use Jquery and semantic, and need to guide the package

index.html code:
Here, if you are A User, you can only access A, Admin can access A,B, and superAdmin can access A,B, and C

<!DOCTYPE html>
<html lang="zh_CN"
      xmlns:th="http://www.thymeleaf.org"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
      xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"
>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Information management platform-home page</title>
    <meta
            name="viewport"
            content="width=device-width, initial-scale=1, maximum-scale=1"
    />
    <title>home page</title>
    <!--semantic-ui-->
    <link
            href="https://cdn.bootcss.com/semantic-ui/2.4.1/semantic.min.css"
            rel="stylesheet"
    />

    <!--<link href="css/index.css" rel="stylesheet">-->
    <link th:href="@{/css/index.css}" rel="stylesheet">

    <!-- <script th:src="@{js/jquery-3.1.1.min.js}"></script> -->
    <script src="js/jquery-3.1.1.min.js"></script>
</head>
<body>
<div class="ui container">
    <div class="ui secondary menu">
        <a class="active item" th:href="@{/index}">
            home page
        </a>

        <a class="active item" th:href="@{/about}">
            about
        </a>
        <!--Login and logout-->
        <div class="right menu">

            <!--If you are not logged in-->
            <!--<div shiro:authorize="!isAuthenticated()">-->
            <div shiro:notAuthenticated="">
                <a class="item" th:href="@{/toLoginPage}">
                    <i class="address card icon"></i> Sign in
                </a>
            </div>

            <!--If logged in-->
            <div shiro:authenticated="">
                <a class="item">
                    <i class="address card icon"></i>
                    user name:<span shiro:principal></span>
                    <!--Role:<span sec:authentication="principal.authorities"></span>-->
                </a>
            </div>

            <div shiro:authenticated="">
                <a class="item" th:href="@{/logout}">
                    <i class="address card icon"></i> cancellation
                </a>
            </div>
        </div>
    </div>

    <div class="ui stackable three column grid">
        <div class="column" shiro:hasAnyRoles="USER,ADMIN,SUPER_ADMIN"><!--There is one of the role class visits-->
            <div class="ui raised segments">
                <div class="ui segment">
                    <a th:href="@{/levelA/a}">L-A-a</a>
                </div>
                <div class="ui segment">
                    <a th:href="@{/levelA/b}">L-A-b</a>
                </div>
                <div class="ui segment">
                    <a th:href="@{/levelA/c}">L-A-c</a>
                </div>
            </div>
        </div>
        <div class="column" shiro:hasAnyRoles="ADMIN,SUPER_ADMIN">
            <div class="ui raised segments">
                <div class="ui segment">
                    <a th:href="@{/levelB/a}">L-B-a</a>
                </div>
                <div class="ui segment">
                    <a th:href="@{/levelB/b}">L-B-b</a>
                </div>
                <div class="ui segment">
                    <a th:href="@{/levelB/c}">L-B-c</a>
                </div>
            </div>
        </div>
        <div class="column" shiro:hasRole="SUPER_ADMIN">
            <div class="ui raised segments">
                <div class="ui segment">
                    <a th:href="@{/levelC/a}">L-C-a</a>
                </div>
                <div class="ui segment">
                    <a th:href="@{/levelC/b}">L-C-b</a>
                </div>
                <div class="ui segment">
                    <a th:href="@{/levelC/c}">L-C-c</a>
                </div>
            </div>
        </div>
        <!-- <div class="column"></div> -->
    </div>

    <div class="ui stacked segment">
        <div class="ui stackable three column grid">
            <div class="column">
                <p>
                    The evening wind blows the white hair between your temples<br/>
                    Heal the scars left by memories<br/>
                    Your eyes are mixed with light and dark. A smile makes flowers<br/>
                    The dusk covers your faltering steps<br/>
                    Go into the picture hidden at the head of the bed<br/>
                    The picture shows you talking with your head down<br/>
                    I still sigh at the size of the world
                </p>
            </div>

            <div class="column">
                <p>

                    Also indulged in childhood love words<br/>
                    No truth, no struggle, no joke<br/>
                    I finally returned my youth to her<br/>
                    With the fingertips pop up in midsummer<br/>
                    The heart moves with the wind<br/>
                    In the name of love, are you willing<br/>
                    ❤
                </p>
            </div>
            <div class="column">
                <img class="ui medium circular image" src="images/001.jpg">
            </div>
        </div>

    </div>

    <div class="ui info message">
        <div class="header">Ideal more than 20 days</div>
        <p>BWH_Steven</p>
    </div>
</div>

</body>
</html>

login.html code:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
>
<head>
    <meta charset="UTF-8">
    <title>User management system-Sign in</title>
    <!-- <script th:src="@{js/jquery-3.1.1.min.js}"></script> -->
    <script src="js/jquery-3.1.1.min.js"></script>
    <link
            href="https://cdn.bootcss.com/semantic-ui/2.4.1/semantic.min.css"
            rel="stylesheet"
    />
</head>
<body>
<h1>User management system-Sign in</h1>
<div class="ui container" style="margin-top: 180px;">
    <div style="text-align: center; margin-bottom: 20px;">
        <h1 class="header">
            Sign in
        </h1>
    </div>

    <div class="ui three column stackable grid login-div">
        <div class="column"></div>
        <div class="column">
            <form id="login" class="ui fluid form segment" th:action="@{/login}" method="post">
                <div class="field">
                    <label class="">user name</label>
                    <div class="ui left icon input">
                        <input type="text" name="username" placeholder=""/>
                        <i class="user icon"></i>
                        <div class="ui corner label">
                            <i class="icon asterisk"></i>
                        </div>
                    </div>
                </div>
                <div class="field">
                    <label class="">password</label>
                    <div class="ui left icon input">
                        <input type="password" name="password" placeholder=""/>
                        <i class="lock icon"></i>
                        <div class="ui corner label">
                            <i class="icon asterisk"></i>
                        </div>
                    </div>
                </div>
                <div class="inline field">
                    <div class="ui checkbox">
                        <input type="checkbox" name="terms"/>
                        <label>Remember the password</label>
                    </div>
                </div>
                <div class="inline field">
                    <input type="submit" class="ui blue submit button">
                </div>
            </form>
        </div>
        <div class="column"></div>
    </div>
</div>


</body>
</html>

success.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>User management system-success</title>
</head>
<body>
<h2>Login successful</h2>
<a href="/index">Return to home page</a>
</body>
</html>

7. Integrate shiro into the project:

(1) Custom Realm:

We need customization, authentication and authorization:

public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserMapper userMapper;

    /**
     * @MethodName doGetAuthorizationInfo Authorized operation
     * @Description Permission configuration class
     * @Param [principalCollection]
     * @Return AuthorizationInfo
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // Get user name information
        String username = (String) principalCollection.getPrimaryPrincipal();
        // Create a simple authorization authentication message
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        // Set the role information obtained from the role table for this user
        authorizationInfo.addRole(userMapper.queryUserByUsername(username).getRole().getRoleName());
        //Set the permission information obtained from the permission table for this user
        authorizationInfo.addStringPermission(userMapper.queryPermissionByUsername(username).getPermissionName());
        return authorizationInfo;
    }

    /**
     * @MethodName doGetAuthenticationInfo Authentication
     * @Description Authentication configuration class
     * @Param [authenticationToken]
     * @Return AuthenticationInfo
     * @Author WangShiLin
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // Obtain the user name according to the Token created in the reception foreground data
        String username = (String) authenticationToken.getPrincipal();

//        UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
//        System.out.println(userToken.getPrincipal());
//        System.out.println(userToken.getUsername());
//        System.out.println(userToken.getPassword());

        // Query relevant user information (entity) through user name
        User user = userMapper.queryUserByUsername(username);
        if (user != null) {
            // Save to Session, optional
            SecurityUtils.getSubject().getSession().setAttribute("user", user);
            // Shiro will do the work of password authentication
            AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), "userRealm");
            return authenticationInfo;
        } else {
            // If null is returned, an exception will be thrown
            return null;
        }
    }
}

(2) Write configuration class shiroConfig:

@Configuration
public class ShiroConfig {

    //Add your own authentication method to the container
    @Bean
    public UserRealm myShiroRealm() {
        return new UserRealm();
    }

    /**
     * Configure security manager SecurityManager
     *
     * @return
     */
    @Bean
    public DefaultWebSecurityManager securityManager() {
        // Add custom Realm
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // Associated Realm
        securityManager.setRealm(myShiroRealm());
        return securityManager;
    }

    /**
     * Configure Shiro filter
     *
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
        // Define shiroFactoryBean
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        // Associate securityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        // Customize the login page. If you log in, you will execute this request, that is, jump to the login page
        shiroFilterFactoryBean.setLoginUrl("toLoginPage");
        // Specify success page
        shiroFilterFactoryBean.setSuccessUrl("/success");
        // Specify unauthorized interface
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");

        // Set custom filter
        Map<String, Filter> filterMap = new LinkedHashMap<>();
        filterMap.put("anyRoleFilter", new MyRolesAuthorizationFilter());
        shiroFilterFactoryBean.setFilters(filterMap);

        // LinkedHashMap is ordered and configured as a sequential interceptor
        Map<String, String> filterChainMap = new LinkedHashMap<>();

        // Configure addresses that can be accessed anonymously. You can add them according to the actual situation and release some static resources. anon means release
        filterChainMap.put("/css/**", "anon");
        filterChainMap.put("/img/**", "anon");
        filterChainMap.put("/js/**", "anon");
        // Specify the page release, for example, the login page allows everyone to log in
        filterChainMap.put("/toLoginPage", "anon");

        // Users starting with "/ user/admin" need identity authentication, and authc means identity authentication
        filterChainMap.put("/user/admin/**", "authc");

        // Page - user needs role authentication
        filterChainMap.put("/levelA/**", "anyRoleFilter[USER,ADMIN,SUPER_ADMIN]");
        filterChainMap.put("/levelB/**", "anyRoleFilter[ADMIN,SUPER_ADMIN]");
        filterChainMap.put("/levelC/**", "anyRoleFilter[SUPER_ADMIN]");

//        filterChainMap.put("/levelA/**", "roles[USER]");
//        filterChainMap.put("/levelB/**", "roles[ADMIN]");
//        filterChainMap.put("/levelC/**", "roles[SUPER_ADMIN]");

        // /user/admin/ All requests under must be subject to permission authentication. Only those with permission of user: [*] can be accessed or set to user:xxx
        filterChainMap.put("/user/admin/**", "perms[user:*]");

        // Configure logoff filter
        filterChainMap.put("/logout", "logout");

        // Save Map to filter
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainMap);
        return shiroFilterFactoryBean;
    }

    /**
     * Integrate thymeleaf
     * @return
     */
    @Bean(name = "shiroDialect")
    public ShiroDialect shiroDialect(){
        return new ShiroDialect();

    }


First, we inject the custom Realm method and dependency into the container

//Add your own authentication method to the container
    @Bean
    public UserRealm myShiroRealm() {
        return new UserRealm();
    }

Then: SecurityManager configuration security manager

/**
     * Configure security manager SecurityManager
     *
     * @return
     */
    @Bean
    public DefaultWebSecurityManager securityManager() {
        // Add custom Realm
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // Realm Association
        securityManager.setRealm(myShiroRealm());
        return securityManager;
    }

Finally, the user-defined filter controls which roles and resources those pages need to access, and setSecurityManager returns a ShiroFilterFactoryBean.

Let's focus on the block and release (map): it is stored in the form of map key value pairs, key stores URL, value stores some corresponding permissions or roles, etc. in fact, the key is well understood. For example, / css /, / user/admin / respectively represent all files in the css folder, and the request path prefix is / user/admin/ URL, and the corresponding value has a certain specification.

Key:
anon: it can be accessed without authentication, that is, tourists can also visit
authc: you must be authenticated to access, that is, you need to log in
roles[xxx]: for example, you can only access with a certain role identity. Note: xxx is a role parameter
perms[xxx]: you must have the relevant permission to access a request and resource. Note: xxx is the permission parameter

(3) Customize a role authentication filter MyRolesAuthorizationFilter:

Because our roles only need one role to access the mapping page, shiro defaults to hasAllRoles, that is, we need to meet all identities to access, so we need to customize a hasanyrole and choose any role.

public class MyRolesAuthorizationFilter extends AuthorizationFilter {

    @SuppressWarnings({"unchecked"})
    public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {

        Subject subject = getSubject(request, response);
        String[] rolesArray = (String[]) mappedValue;

        if (rolesArray == null || rolesArray.length == 0) {
            //no roles specified, so nothing to check - allow access.
            return false;
        }

        List<String> roles = CollectionUtils.asList(rolesArray);
        boolean[] hasRoles = subject.hasRoles(roles);
        for (boolean hasRole : hasRoles) {
            if (hasRole) {
                return true;
            }
        }
        return false;
    }
}

(4) Finally, the controller

Controller is the front-end controller of springMvc. It receives any request and returns the corresponding specified page (mapping).
First, we write the mapping of all pages,

PageController:

@Controller
public class PageController {

    @RequestMapping({"/", "index"})
    public String index() {
        return "index";
    }

    @RequestMapping("about")
    public String toAboutPage() {
        return "redirect:http://www.ideal-20.cn";
    }

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

    @RequestMapping("/levelA/{name}")
    public String toLevelAPage(@PathVariable("name") String name) {
        return "views/L-A/" + name;
    }

    @RequestMapping("/levelB/{name}")
    public String toLevelBPage(@PathVariable("name") String name) {
        return "views/L-B/" + name;
    }

    @RequestMapping("/levelC/{name}")
    public String toLevelCPage(@PathVariable("name") String name) {
        return "views/L-C/" + name;
    }

    @RequestMapping("/unauthorized")
    public String toUnauthorizedPage() {
        return "views/unauthorized";
    }

    @RequestMapping("/success")
    public String toSuccessPage() {
        return "views/success";
    }

}

UserController:
The above two mappings are just tests, mainly the login method, which can create a token according to the data input by our foreground. If the token can be authenticated, it will return to the success page, otherwise it will fail.

@Controller
public class UserController {
    @RequestMapping("/user/queryAll")
    @ResponseBody
    public String queryAll() {
        return "This is user/queryAll method";
    }

    @RequestMapping("/user/admin/add")
    @ResponseBody
    public String adminAdd() {
        return "This is user/adminAdd method";
    }

    @RequestMapping("/login")
    public String login(String username, String password, HttpServletRequest request) {
        // Since it is obtained according to the name parameter, I encapsulate it here
        User user = new User();
        user.setUsername(username);
        user.setPassword(password);

        // Create a Token content, which is essentially based on the user name and password of the foreground (not necessarily correct)
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        // Obtain the subject authentication principal (here is the logged in user)
        Subject subject = SecurityUtils.getSubject();
        try{
            // When authentication starts, you will jump to the user-defined UserRealm
            subject.login(token);
            // Can be stored in session
            request.getSession().setAttribute("user", user);
            return "views/success";
        }catch(Exception e){
            // Catch exception
            e.printStackTrace();
            request.getSession().setAttribute("user", user);
            request.setAttribute("errorMsg", "Brother, wrong user name or password");
            return "views/login";
        }
    }
}

8. Final effect:

The first is http://localhost:8080/index

Login interface:

After the form is submitted, the value is returned to the Login method of UserController. Authentication:

In this way, we have successfully logged in and have the permission of superAdmin. We can view a, B and C

User Zhang San can only see A

So far, this blog draws lessons from: Blog , if you need the source code, please check this blog.

Tags: Mybatis Shiro SSM

Posted by MStaniszczak on Thu, 05 May 2022 06:46:47 +0300