Spring Security【认证成功后的处理方式、退出登录 、Remember Me、RBAC 、权限表设计】(二)-全面详解(学习总结---从入门到深化)

 

 

目录

Spring Security认证_认证成功后的处理方式

Spring Security认证_认证失败后的处理方式

Spring Security认证_退出登录 

         Spring Security认证_退出成功处理器 

Spring Security认证_Remember Me

Spring Security授权_RBAC 

Spring Security授权_权限表设计


Spring Security认证_认证成功后的处理方式

登录成功后,如果除了跳转页面还需要执行一些自定义代码时, 如:统计访问量,推送消息等操作时,可以自定义登录成功处理器。

1、自定义登录成功处理器

public class MyLoginSuccessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest
request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        // 拿到登录用户的信息
        UserDetails userDetails = (UserDetails)authentication.getPrincipal();
        System.out.println("用户名:"+userDetails.getUsername());
        System.out.println("一些操作...");
        // 重定向到主页
        response.sendRedirect("/main");
   }
}

2、配置登录成功处理器

http.formLogin() // 使用表单登录
   .loginPage("/login.html") // 自定义登录页面
   .usernameParameter("username") // 表单中的用户名项
   .passwordParameter("password") // 表单中的密码项
   .loginProcessingUrl("/login") // 登录路径,表单向该路径提交,提交后自动执行 UserDetailsService的方法
    //.successForwardUrl("/main") //登录成功后跳转的路径
   .successHandler(new MyLoginSuccessHandler()) //登录成功处理器
   .failureForwardUrl("/fail"); //登录失败后跳转的路径

 

Spring Security认证_认证失败后的处理方式

登录失败后,如果除了跳转页面还需要执行一些自定义代码时, 如:统计失败次数,记录日志等,可以自定义登录失败处理器。

1、自定义登录失败处理器

public class MyLoginFailureHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
        System.out.println("记录失败日志...");
        response.sendRedirect("/fail");
   }
}

2、配置登录失败处理器

http.formLogin() // 使用表单登录
   .loginPage("/login.html") // 自定义登录页面
   .usernameParameter("username") // 表单中的用户名项
   .passwordParameter("password") // 表单中的密码项
   .loginProcessingUrl("/login") // 登录路径,表单向该路径提交,提交后自动执行UserDetailsService的方法
    //.successForwardUrl("/main") //登录成功后跳转的路径
   .successHandler(new MyLoginSuccessHandler()) //登录成功处理器
    //.failureForwardUrl("/fail") //登录失败后跳转的路径
   .failureHandler(new MyLoginFailureHandler()); //登录失败处理器
    // 需要认证的资源
http.authorizeRequests()
   .antMatchers("/login.html").permitAll() //登录页不需要认证
   .antMatchers("/fail").permitAll() //失败页不需要认证
   .anyRequest().authenticated(); //其余所有请求都需要认证

Spring Security认证_退出登录 

 在系统中一般都有退出登录的操作。退出登录后,Spring Security 进行了以下操作:

1、清除认证状态

2、销毁HttpSession对象 

3、跳转到登录页面

在Spring Security中,退出登录的写法如下:

 1、配置退出登录的路径和退出后跳转的路径

// 退出登录配置
http.logout()
   .logoutUrl("/logout") // 退出登录路径
   .logoutSuccessUrl("/login.html") // 退出登录后跳转的路径
   .clearAuthentication(true) //清除认证状态,默认为true
   .invalidateHttpSession(true); // 销毁HttpSession对象,默认为true

2、在网页中添加退出登录超链接

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页面</title>
</head>
<body>
  <h1>主页面</h1>
  <a href="/logout">退出登录</a>
</body>
</html>

Spring Security认证_退出成功处理器 

我们也可以自定义退出成功处理器,在退出后清理一些数据,写法 如下:

1、自定义退出成功处理器

public class MyLogoutSuccessHandler implements LogoutSuccessHandler {
    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
        System.out.println("清除一些数据...");
        response.sendRedirect("/login.html");
   }
}

2、配置退出成功处理器

// 退出登录配置
http.logout()
   .logoutUrl("/logout") // 退出登录路径
    //               .logoutSuccessUrl("/login.html") // 退出登录后跳转的路径
   .clearAuthentication(true) //清除认证状态,默认为true
   .invalidateHttpSession(true) // 销毁HttpSession对象,默认为 true
   .logoutSuccessHandler(new MyLogoutSuccessHandler()); //自定义退出成功处
理器

 Spring Security认证_Remember Me

Spring Security中Remember Me为“记住我”功能,即下次访问系统 时无需重新登录。当使用“记住我”功能登录后,Spring Security会 生成一个令牌,令牌一方面保存到数据库中,另一方面生成一个叫 remember-me 的Cookie保存到客户端。之后客户端访问项目时自动携 带令牌,不登录即可完成认证。

 1、编写“记住我”配置类

@Configuration
public class RememberMeConfig {
    @Autowired
    private DataSource dataSource;
    // 令牌Repository
    @Bean
    public PersistentTokenRepository getPersistentTokenRepository() {
        // 为Spring Security自带的令牌控制器设置数据源
        JdbcTokenRepositoryImpl jdbcTokenRepositoryImpl = new JdbcTokenRepositoryImpl();
        jdbcTokenRepositoryImpl.setDataSource(dataSource);
        //自动建表,第一次启动时需要,第二次启动时注释掉
        //       jdbcTokenRepositoryImpl.setCreateTableOnStartup(true);
        return jdbcTokenRepositoryImpl;
   }
}

2、修改Security配置类

// 记住我配置
http.rememberMe()
       .userDetailsService(userDetailsService)//登录逻辑交给哪个对象
       .tokenRepository(repository) //持久层对象
       .tokenValiditySeconds(30); //保存时间,单位:秒

3、在登录页面添加“记住我”复选框

<form class="form" action="/login" method="post">
    <input type="text" placeholder="用户名" name="username">
    <input type="password" placeholder="密码" name="password">
    <input type="checkbox" name="remember-me" value="true"/>记住我</br>
    <button type="submit">登录</button>
</form>

Spring Security授权_RBAC 

 授权即认证通过后,系统给用户赋予一定的权限,用户只能根据权 限访问系统中的某些资源。RBAC是业界普遍采用的授权方式,它有 两种解释:

Role-Based Access Control

基于角色的访问控制,即按角色进行授权。比如在企业管理系统 中,主体角色为总经理可以查询企业运营报表。逻辑为:

if(主体.hasRole("总经理角色")){
 查询运营报表
}

如果查询企业运营报表的角色变化为总经理和股东,此时就需要修 改判断逻辑代码:

if(主体.hasRole("总经理角色") || 主体.hasRole("股东角色")){
     查询运营报表
}

此时我们可以发现,当需要修改角色的权限时就需要修改授权的相 关代码,系统可扩展性差。

Resource-Based Access Control

基于资源的访问控制,即按资源(或权限)进行授权。比如在企业 管理系统中,用户必须 具有查询报表权限才可以查询企业运营报 表。逻辑为:

if(主体.hasPermission("查询报表权限")){
   查询运营报表
}

这样在系统设计时就已经定义好查询报表的权限标识,即使查询报 表所需要的角色变化为总经理和股东也不需要修改授权代码,系统 可扩展性强。该授权方式更加常用。

Spring Security授权_权限表设计

 用户和权限的关系为多对多,即用户拥有多个权限,权限也属于多 个用户,所以建表方式如下:

 这种方式需要指定用户有哪些权限,如:张三有查询工资的权限, 即在用户权限中间表中添加一条数据,分别记录张三和查询工资权 限ID。但在系统中权限数量可能非常庞大,如果一条一条添加维护 数据较为繁琐。所以我们通常的做法是再加一张角色表:

 用户角色,角色权限都是多对多关系,即一个用户拥有多个角色, 一个角色属于多个用户;一个角色拥有多个权限,一个权限属于多 个角色。这种方式需要指定用户有哪些角色,而角色又有哪些权限。

如:张三拥有总经理的角色,而总经理拥有查询工资、查询报表的 权限,这样张三就拥有了查询工资、查询报表的权限。这样管理用 户时只需管理少量角色,而管理角色时也只需要管理少量权限即可。接下来我们创建五张表:

CREATE TABLE `users`  (`uid` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `phone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`uid`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 3
  CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `users` VALUES (1, 'xiaotong','$2a$10$Eqv9PRMl6bPt5BiwgPr2eucgyl.E.xLENt4b
vfDvv7DyS5AVPT.U6', '13812345678');
CREATE TABLE `role`  (
  `rid` int(11) NOT NULL AUTO_INCREMENT,
  `roleName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `roleDesc` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`rid`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 4
CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `role` VALUES (1,'总经理','管理整个公司');
INSERT INTO `role` VALUES (2,'股东','参与公司决策');
INSERT INTO `role` VALUES (3,'财务','管理公司资产');
CREATE TABLE `permission`  (
  `pid` int(11) NOT NULL AUTO_INCREMENT,
  `permissionName` varchar(255) CHARACTER
SET utf8 COLLATE utf8_general_ci NULL
DEFAULT NULL,
  `url` varchar(255) CHARACTER SET utf8
COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`pid`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 4
CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `permission` VALUES (1,'查询报表', '/reportform/find');
INSERT INTO `permission` VALUES (2,'查询工资', '/salary/find');
INSERT INTO `permission` VALUES (3,'查询税务', '/tax/find');
CREATE TABLE `users_role`  (
  `uid` int(255) NOT NULL,
  `rid` int(11) NOT NULL,
  PRIMARY KEY (`uid`, `rid`) USING BTREE,
  INDEX `rid`(`rid`) USING BTREE,
  CONSTRAINT `users_role_ibfk_1` FOREIGN KEY(`uid`) REFERENCES `users` (`uid`) ON DELETE
RESTRICT ON UPDATE RESTRICT,
  CONSTRAINT `users_role_ibfk_2` FOREIGN KEY(`rid`) REFERENCES `role` (`rid`) ON DELETE
RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB CHARACTER SET = utf8
COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `users_role` VALUES (1, 2);
INSERT INTO `users_role` VALUES (1, 3);
CREATE TABLE `role_permission`  (
  `rid` int(11) NOT NULL,
  `pid` int(11) NOT NULL,
   PRIMARY KEY (`rid`, `pid`) USING BTREE,
   INDEX `pid`(`pid`) USING BTREE,
   CONSTRAINT `role_permission_ibfk_1` FOREIGN KEY (`rid`) REFERENCES `role`
(`rid`) ON DELETE RESTRICT ON UPDATE
RESTRICT,
  CONSTRAINT `role_permission_ibfk_2`
FOREIGN KEY (`pid`) REFERENCES `permission`
(`pid`) ON DELETE RESTRICT ON UPDATE
RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8
COLLATE = utf8_general_ci ROW_FORMAT =
Dynamic;
INSERT INTO `role_permission` VALUES (1, 1);
INSERT INTO `role_permission` VALUES (2, 1);
INSERT INTO `role_permission` VALUES (1, 2);
INSERT INTO `role_permission` VALUES (3, 2);
INSERT INTO `role_permission` VALUES (1, 3);
INSERT INTO `role_permission` VALUES (2, 3);

猜你喜欢

转载自blog.csdn.net/m0_58719994/article/details/131797434
今日推荐