最近在做一个期末作品,就是应用 ssm+thymeleaf+vue+shiro 实现一个具备 权限登录,且能实现用户信息增删查改 的这么一个我的项目,上面仅仅是实现 权限认证和登录。为什么我选 shiro,而不选 spring Security,是因为我试过,security 切实是比拟难,封装的太厉害了,哈哈哈哈,所以果决放弃,抉择 shiro 进行。
下一篇还实现了增删查改,应用 vue,然而没有前后端拆散,博客链接
!github 源码连贯,须要请自行下载。
提醒,这个我的项目曾经有了增删查改,跟着上面的博客做,也能做进去页面跳转权限,然而没有增删查改。
以下是学习 shiro 的一个小 Demo:
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:
@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>
<!-- 定义封装 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());
}
}
测试后果:
失去了查问后果
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>
<!--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
登录界面:
表单提交后,就返回值到 UserController 那个 Login 办法,认证:
这样咱们就登录胜利了,并且是 superAdmin 的权限,能够查看 A,B,C
而用户张三,只能看见 A
到此结束,本博客借鉴:博客, 须要源码的请查看此博客。