超詳細,附源碼!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

到此結束,本博客借鑑:博客,須要源碼的請查看此博客。

相關文章
相關標籤/搜索