超详细,附源码!SpringBoot+shiro+mybatis+Thymeleaf实现权限登陆

最近在作一个期末做品,就是使用ssm+thymeleaf+vue+shiro完成一个具备权限登陆,且能实现用户信息增删查改的这么一个项目,下面仅仅是实现权限认证和登陆。为何我选shiro,而不选spring Security,是由于我试过,security实在是比较难,封装的太厉害了,哈哈哈哈,因此果断放弃,选择shiro进行。css

下一篇还实现了增删查改,使用vue,可是没有先后端分离,博客连接html

!github源码链接,须要请自行下载。前端

提示,这个项目已经有了增删查改,跟着下面的博客作,也能作出来页面跳转权限,可是没有增删查改。vue

如下是学习shiro的一个小Demo:java

1.首先是底层数据库:

-- ----------------------------
-- Table structure for role
-- ----------------------------
CREATE TABLE `role`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '角色表主键',
  `role_name` varchar(32) DEFAULT NULL COMMENT '角色名称',
  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 '用户主键',
  `username` varchar(32) NOT NULL COMMENT '用户名',
  `password` varchar(32) NOT NULL COMMENT '密码',
  `role_id` int(11) DEFAULT NULL COMMENT '与role角色表联系的外键',
  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_name` varchar(50) NOT NULL COMMENT '权限名',
  `role_id` int(11) DEFAULT NULL COMMENT '与role角色表联系的外键',
  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.建立spring boot项目,用maven构建

建立实体类(User,Role,Permissions):
User:mysql

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String username;
    private String password;
    //用户对应的角色集合
    private Role role;
}

Role:jquery

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


}

Permissions:git

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

咱们须要知道三个实体类之间的关系,User与Role一对一,Role与Permissions一对一,固然也能够把它都写成多对多,这就须要去更改数据库文件,和实体类了。github

3.在pom.xml添加相关依赖:

下面只给出相关依赖源web

<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.整合mybatis和springboot:

就只须要建立一个dao层,一个服务层,须要记住要添加注解
(1)mapper配置文件(也可使用注解形式):

<?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>
    <!-- 定义封装 User和 role 的 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>
        <!-- 配置封装 UserPojo 的内容 -->
        <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>
    <!-- 定义封装 permission 和 role 的 resultMap -->
    <resultMap id="permissionRoleMap" type="com.example.csy.entity.Permissions">
        <id property="id" column="id"/>
        <result property="permissionName" column="permission_name"></result>
        <!-- 配置封装 Role 的内容 -->
        <association property="role" javaType="com.example.csy.entity.Role">
            <id property="id" column="id"></id>
            <!--property是实体类中被赋值的参数名,column是数据库的列名-->
            <result property="roleName" column="role_name"></result>
        </association>
    </resultMap>
</mapper>

(2)DAO层:

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

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

(3)service层:

@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);
    }
}

弄到这里,咱们的mybatis+springboot整合也基本结束,因此在测试类里测试一下:

@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());
    }
}

测试结果:
获得了查询结果

QQ截图20201120111727.png

6.整合Thymeleaf进来:

前端页面:
在html页面咱们整合了Thymeleaf,使用了Jquery,semantic,须要导包
QQ截图20201120131847.png
QQ截图20201120131359.png

index.html代码:
在这里,若是是User就只能访问A,Admin能访问A,B,superAdmin能访问A,B,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>信息管理平台-首页</title>
    <meta
            name="viewport"
            content="width=device-width, initial-scale=1, maximum-scale=1"
    />
    <title>首页</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}">
            首页
        </a>

        <a class="active item" th:href="@{/about}">
            关于
        </a>
        <!--登陆注销-->
        <div class="right menu">

            <!--若是未登陆-->
            <!--<div shiro:authorize="!isAuthenticated()">-->
            <div shiro:notAuthenticated="">
                <a class="item" th:href="@{/toLoginPage}">
                    <i class="address card icon"></i> 登陆
                </a>
            </div>

            <!--若是已登陆-->
            <div shiro:authenticated="">
                <a class="item">
                    <i class="address card icon"></i>
                    用户名:<span shiro:principal></span>
                    <!--角色:<span sec:authentication="principal.authorities"></span>-->
                </a>
            </div>

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

    <div class="ui stackable three column grid">
        <div class="column" shiro:hasAnyRoles="USER,ADMIN,SUPER_ADMIN"><!--有其中任一一个角色课访问-->
            <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>
                    晚风吹起你鬓间的白发<br/>
                    抚平回忆留下的疤<br/>
                    你的眼中 明暗交杂 一笑生花<br/>
                    暮色遮住你蹒跚的步伐<br/>
                    走进床头藏起的画<br/>
                    画中的你 低着头说话<br/>
                    我仍感叹于世界之大
                </p>
            </div>

            <div class="column">
                <p>

                    也沉醉于儿时情话<br/>
                    不剩真假 不作挣扎 无谓笑话<br/>
                    我终将青春还给了她<br/>
                    连同指尖弹出的盛夏<br/>
                    心之所动 就随风去了<br/>
                    以爱之名 你还愿意吗<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">理想二旬不止</div>
        <p>BWH_Steven</p>
    </div>
</div>

</body>
</html>

login.html代码:

<!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>用户管理系统-登陆</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>用户管理系统-登陆</h1>
<div class="ui container" style="margin-top: 180px;">
    <div style="text-align: center; margin-bottom: 20px;">
        <h1 class="header">
            登陆
        </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="">用户名</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="">密码</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>记住密码</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>用户管理系统-成功</title>
</head>
<body>
<h2>登陆成功</h2>
<a href="/index">返回主页</a>
</body>
</html>

7.将shiro整合到项目里:

(1)自定义Realm:

咱们须要自定义,认证和受权:

public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserMapper userMapper;

    /**
     * @MethodName doGetAuthorizationInfo 受权操做
     * @Description 权限配置类
     * @Param [principalCollection]
     * @Return AuthorizationInfo
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 获取用户名信息
        String username = (String) principalCollection.getPrimaryPrincipal();
        // 建立一个简单受权验证信息
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        // 给这个用户设置从 role 表获取到的角色信息
        authorizationInfo.addRole(userMapper.queryUserByUsername(username).getRole().getRoleName());
        //给这个用户设置从 permission 表获取的权限信息
        authorizationInfo.addStringPermission(userMapper.queryPermissionByUsername(username).getPermissionName());
        return authorizationInfo;
    }

    /**
     * @MethodName doGetAuthenticationInfo 身份验证
     * @Description 认证配置类
     * @Param [authenticationToken]
     * @Return AuthenticationInfo
     * @Author WangShiLin
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 根据在接受前台数据建立的 Token 获取用户名
        String username = (String) authenticationToken.getPrincipal();

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

        // 经过用户名查询相关的用户信息(实体)
        User user = userMapper.queryUserByUsername(username);
        if (user != null) {
            // 存入 Session,可选
            SecurityUtils.getSubject().getSession().setAttribute("user", user);
            // 密码认证的工做,Shiro 来作
            AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), "userRealm");
            return authenticationInfo;
        } else {
            // 返回 null 即会抛异常
            return null;
        }
    }
}

(2)写配置类shiroConfig:

@Configuration
public class ShiroConfig {

    //将本身的验证方式加入容器
    @Bean
    public UserRealm myShiroRealm() {
        return new UserRealm();
    }

    /**
     * 配置安全管理器 SecurityManager
     *
     * @return
     */
    @Bean
    public DefaultWebSecurityManager securityManager() {
        // 将自定义 Realm 加进来
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 关联 Realm
        securityManager.setRealm(myShiroRealm());
        return securityManager;
    }

    /**
     * 配置 Shiro 过滤器
     *
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
        // 定义 shiroFactoryBean
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        // 关联 securityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        // 自定义登陆页面,若是登陆的时候,就会执行这个请求,即跳转到登陆页
        shiroFilterFactoryBean.setLoginUrl("toLoginPage");
        // 指定成功页面
        shiroFilterFactoryBean.setSuccessUrl("/success");
        // 指定未受权界面
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");

        // 设置自定义 filter
        Map<String, Filter> filterMap = new LinkedHashMap<>();
        filterMap.put("anyRoleFilter", new MyRolesAuthorizationFilter());
        shiroFilterFactoryBean.setFilters(filterMap);

        // LinkedHashMap 是有序的,进行顺序拦截器配置
        Map<String, String> filterChainMap = new LinkedHashMap<>();

        // 配置能够匿名访问的地址,能够根据实际状况本身添加,放行一些静态资源等,anon 表示放行
        filterChainMap.put("/css/**", "anon");
        filterChainMap.put("/img/**", "anon");
        filterChainMap.put("/js/**", "anon");
        // 指定页面放行,例如登陆页面容许全部人登陆
        filterChainMap.put("/toLoginPage", "anon");

        // 以“/user/admin” 开头的用户须要身份认证,authc 表示要进行身份认证
        filterChainMap.put("/user/admin/**", "authc");

        // 页面 -用户须要角色认证
        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/ 下的全部请求都要通过权限认证,只有权限为 user:[*] 的能够访问,也能够具体设置到 user:xxx
        filterChainMap.put("/user/admin/**", "perms[user:*]");

        // 配置注销过滤器
        filterChainMap.put("/logout", "logout");

        // 将Map 存入过滤器
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainMap);
        return shiroFilterFactoryBean;
    }

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

    }

首先咱们将自定义的Realm方法,依赖注入进来到容器

//将本身的验证方式加入容器
    @Bean
    public UserRealm myShiroRealm() {
        return new UserRealm();
    }

而后是:SecurityManager配置安全管理器

/**
     * 配置安全管理器 SecurityManager
     *
     * @return
     */
    @Bean
    public DefaultWebSecurityManager securityManager() {
        // 将自定义 Realm 加进来
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 关联 Realm
        securityManager.setRealm(myShiroRealm());
        return securityManager;
    }

最后就是自定义的过滤器,控制那些页面须要什么样的角色才能访问,哪些资源须要谁才能访问,而且setSecurityManager,返回一个ShiroFilterFactoryBean。

重点说一下拦截放行(Map)这块:经过 map 键值对的形式存储,key 存储 URL ,value 存储对应的一些权限或者角色等等,其实 key 这块仍是很好理解的,例如 :/css/、/user/admin/ 分别表明 css 文件夹下的全部文件,以及请求路径前缀为 /user/admin/ URL,而对应的 value 就有必定的规范了。

关键:
anon:无需认证,便可访问,也就是游客也能够访问
authc:必须认证,才能访问,也就是例如须要登陆后
roles[xxx] :好比拥有某种角色身份才能访问 ,注:xxx为角色参数
perms[xxx]:必须拥有对某个请求、资源的相关权限才能访问,注:xxx为权限参数

(3)自定义一个角色认证过滤器MyRolesAuthorizationFilter:

由于咱们的角色,只需用有一个角色就能访问到映射页面,shiro默认是hasAllRoles,也就是说,咱们要知足全部的身份才能访问,因此须要咱们自定义一个hasAnyRoles,任选其一角色便可。

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)最后就是controller

controller是springMvc的前端控制器,接收什么请求,而且返回对应指定的页面(映射)。
首先咱们先将因此页面的映射写好,

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:
上面那两个映射,只是测试,主要是那个login方法,他能够根据咱们前台输入的数据,并建立一个token,若是该token能被认证,即返回成功页面,不然就失败。

@Controller
public class UserController {
    @RequestMapping("/user/queryAll")
    @ResponseBody
    public String queryAll() {
        return "这是 user/queryAll 方法";
    }

    @RequestMapping("/user/admin/add")
    @ResponseBody
    public String adminAdd() {
        return "这是 user/adminAdd 方法";
    }

    @RequestMapping("/login")
    public String login(String username, String password, HttpServletRequest request) {
        // 因为是根据name参数获取的,我这里封装了一下
        User user = new User();
        user.setUsername(username);
        user.setPassword(password);

        // 建立出一个 Token 内容本质基于前台的用户名和密码(不必定正确)
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        // 获取 subject 认证主体(这里也就是如今登陆的用户)
        Subject subject = SecurityUtils.getSubject();
        try{
            // 认证开始,这里会跳转到自定义的 UserRealm 中
            subject.login(token);
            // 能够存储到 session 中
            request.getSession().setAttribute("user", user);
            return "views/success";
        }catch(Exception e){
            // 捕获异常
            e.printStackTrace();
            request.getSession().setAttribute("user", user);
            request.setAttribute("errorMsg", "兄弟,用户名或密码错误");
            return "views/login";
        }
    }
}

8.最终效果:

首先是http://localhost:8080/index

QQ截图20201120134737.png

登陆界面:

QQ截图20201120134930.png

表单提交后,就返回值到UserController那个Login方法,认证:

QQ截图20201120135024.png

这样咱们就登陆成功了,而且是superAdmin的权限,能够查看A,B,C

QQ截图20201120135156.png

而用户张三,只能看见A
QQ截图20201120135305.png

到此结束,本博客借鉴:博客,须要源码的请查看此博客。

相关文章
相关标签/搜索