写点什么

SpringBoot+shiro+mybatis 实现权限登录

  • 2021 年 11 月 11 日
  • 本文字数:7117 字

    阅读完需:约 23 分钟

2.创建 spring boot 项目,用 maven 构建


==============================================================================================


创建实体类(User,Role,Permissions):


User:


@Data


@AllArgsConstructor


@NoArgsConstructor


public class User {


private Integer id;


private String username;


private String password;


//用户对应的角色集合


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;


}


我们需要知道三个实体类之间的关系,User 与 Role 一对一,Role 与 Permissions 一对一,当然也可以把它都写成多对多,这就需要去更改数据库文件,和实体类了。


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


=====================================================================================


下面只给出相关依赖源


<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>


<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>


<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>


<resultMap id="permissionRoleMap" type="com.example.csy.entity.Permissions">


<id property="id" column="id"/>


<result property="permissionName" column="permission_name"></result>


<association property="role" javaType="com.example.csy.entity.Role">


<id property="id" column="id"></id>


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


}


}


测试结果:


得到了查询结果



6.整合 Thymeleaf 进来:


====================================================================================


前端页面:


在 html 页面我们整合了 Thymeleaf,使用了 Jquery,semantic,需要导包




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>


<link


href="https://cdn.bootcss.com/semantic-ui/2.4.1/semantic.min.css"


rel="stylesheet"


/>


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


<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: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>


</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="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>


<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>


【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


<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 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


*/

评论

发布
暂无评论
SpringBoot+shiro+mybatis实现权限登录