• 【Spring-Security】Re08 Thymeleaf权限控制 与 退出功能


    一、需要的组件支持:

    新版本这里的组件有些问题:

    https://blog.csdn.net/qq_36488647/article/details/104532754
    https://blog.csdn.net/YzVermicelli/article/details/106417610

    然后我这里就是需要降低下一个版本,Maven依赖就不会爆红了【SpringBoot2.3.4版本】

    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity5</artifactId>
        <version>3.0.3.RELEASE</version>
    </dependency>

    Security本体的组件:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-test</artifactId>
    </dependency>

    Web支持 + Thymeleaf模板引擎:

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

    二、属性获取

    然后要使用的模板目录内的页面文件需要导入Thyemleaf + Security的约束

    注意一定是使用这个约束地址,新版本的地址反而无效了。。。

    <html lang="en"xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">

    我们可以获取的用户信息:

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
    <head>
        <meta charset="UTF-8">
        <title>Main-Page</title>
    </head>
    <body>
        <h3>This is main page</h3>
    
        <p>登录账号 <span sec:authentication="name"></span></p>
        <p>登录账号 <span sec:authentication="principal.username"></span></p>
        <p>凭证 <span sec:authentication="credentials"></span></p>
        <p>权限角色集合 <span sec:authentication="authorities"></span></p>
        <p>IP地址 <span sec:authentication="details.remoteAddress"></span></p>
        <p>会话ID <span sec:authentication="details.sessionId"></span></p>
    </body>
    </html>

    访问查看:

    三、权限判断:

    现在我在用户权限赋予中增加角色和权限:

    package cn.zeal4j.service;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.authority.AuthorityUtils;
    import org.springframework.security.core.userdetails.User;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.stereotype.Service;
    
    /**
     * @author Administrator
     * @file IntelliJ IDEA Spring-Security-Tutorial
     * @create 2020 09 27 21:57
     */
    @Service
    public class UserDetailsServiceImpl implements UserDetailsService {
    
        @Autowired
        private PasswordEncoder passwordEncoder;
    
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    
            // 1、通过提供的用户名参数访问数据库,查询记录返回过来,如果记录不存在则抛出异常
            // username = "admin";
            if (!"admin".equals(username)) throw new UsernameNotFoundException("用户名不存在");
    
            // 2、查询出来的凭证是被加密了的,这里是模拟查询的密码
            String encode = passwordEncoder.encode("123456");
    
            // 权限不可以为空,所以需要这么一个工具方法简单实现
            return new User(username, encode, AuthorityUtils.commaSeparatedStringToAuthorityList("admin,normal,ROLE_vip-01,ROLE_A,ROLE_B,ROLE_C,/create,/update,/delete"));
        }
    }

    在页面中的权限控制案例:

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
    <head>
        <meta charset="UTF-8">
        <title>Main-Page</title>
        <style type="text/css">
            h3, p {
                text-align: center;
            }
        </style>
    </head>
    <body>
        <h3>This is main page</h3>
    
        <p>登录账号 <span sec:authentication="name"></span></p>
        <p>登录账号 <span sec:authentication="principal.username"></span></p>
        <p>凭证 <span sec:authentication="credentials"></span></p>
        <p>权限角色集合 <span sec:authentication="authorities"></span></p>
        <p>IP地址 <span sec:authentication="details.remoteAddress"></span></p>
        <p>会话ID <span sec:authentication="details.sessionId"></span></p>
    
        <h3>权限控制展示</h3>
        <p> <button sec:authorize="hasRole('A')" >角色A</button> </p>
        <p> <button sec:authorize="hasRole('B')" >角色B</button> </p>
        <p> <button sec:authorize="hasRole('C')" >角色C</button> </p>
        <p> <button sec:authorize="hasRole('D')" >角色D</button> </p>
        
        <p> <button sec:authorize="hasAuthority('/create')" >创建权限</button> </p>
        <p> <button sec:authorize="hasAuthority('/update')" >更新权限</button> </p>
        <p> <button sec:authorize="hasAuthority('/delete')" >删除权限</button> </p>
        <p> <button sec:authorize="hasAuthority('/select')" >查询权限</button> </p>
    </body>
    </html>

    访问查看:

    可以看到角色D和SELECT权限都没有,Security对应也不会显示这些按钮

    四、退出功能:

    Security默认提供了Logout退出控制

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Project-Index</title>
    </head>
    <body>
        <h1>Hello Spring-Security !!!</h1>
        <a href="/logout">click to logout</a>
    </body>
    </html>

    点击会自动重定向到登录页面来,并且会有一个logout参数值在地址中:

    如果不希望附带这个参数,则需要配置退出的处理:

    package cn.zeal4j.configuration;
    
    import cn.zeal4j.handler.CustomAccessDeniedHandler;
    import cn.zeal4j.handler.FarsAuthenticationFailureHandler;
    import cn.zeal4j.handler.FarsAuthenticationSuccessHandler;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.HttpMethod;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.core.parameters.P;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.security.web.access.AccessDeniedHandler;
    import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
    import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
    
    import javax.sql.DataSource;
    
    /**
     * @author Administrator
     * @file IntelliJ IDEA Spring-Security-Tutorial
     * @create 2020 09 27 21:55
     */
    @Configuration
    public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private AccessDeniedHandler accessDeniedHandler;
        @Qualifier("userDetailsServiceImpl")
        @Autowired
        private UserDetailsService userDetailsService;
        @Autowired
        private DataSource dataSource;
        @Autowired
        private PersistentTokenRepository persistentTokenRepository;
    
        @Bean
        public PersistentTokenRepository getPersistentTokenRepository() {
            JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
            jdbcTokenRepository.setDataSource(dataSource); // 数据源注入
            jdbcTokenRepository.setCreateTableOnStartup(false); // 由Security完成Token表的创建,如果有了就设置false关闭
            return jdbcTokenRepository;
        }
    
        @Bean
        public PasswordEncoder getPasswordEncoder() {
            return new BCryptPasswordEncoder();
        }
    
        @Override
        protected void configure(HttpSecurity httpSecurity) throws Exception {
            httpSecurity.formLogin(). // 设置登陆行为方式为表单登陆
                    // 登陆请求参数设置
                    usernameParameter("username").
                    passwordParameter("password").
    
                    loginPage("/login.html"). // 设置登陆页面URL路径
                    loginProcessingUrl("/login.action"). // 设置表单提交URL路径
    
                    successForwardUrl("/main.page"). // 设置认证成功跳转URL路径 POST请求
                    failureForwardUrl("/error.page");  // 设置认证失败跳转URL路径 POST请求
    
                    //  successHandler(new FarsAuthenticationSuccessHandler("https://www.acfun.cn/")). // 使用自定义的重定向登陆
                    //  failureHandler(new FarsAuthenticationFailureHandler("/error.html")).; // 跨域处理,不需要跳转了
    
            httpSecurity.authorizeRequests().
                    regexMatchers(HttpMethod.POST, "正则表达式").permitAll(). // 还可以对符合正则表达式的请求方式进行要求,这个属性使用来制定请求的方式
    
                    antMatchers("/**/*.js", "/**/*.css", "/**/images/*.*").permitAll(). // 静态资源放行
    
                    antMatchers("/login.html").permitAll(). // 登陆页面允许任意访问
                    antMatchers("/error.html").permitAll(). // 失败跳转后重定向的页面也需要被允许访问
                    antMatchers("/admin.page").hasAnyAuthority("admin").
    
                    /*antMatchers("/vip-01.page").hasAnyAuthority("vip-01").*/
                    antMatchers("/vip-01.page").hasRole("vip-01").
                    antMatchers("/ip.page").hasIpAddress("192.168.43.180").
    
                    // mvcMatchers("/main.page").servletPath("/xxx").permitAll(). // mvcMatchers资源放行匹配
                    // antMatchers("/xxx/main.page").permitAll(). // 或者多写MSP的前缀
    
                    anyRequest().authenticated(); // 其他请求均需要被授权访问
                    // anyRequest().access("@customServiceImpl.hasPermission(request, authentication)"); // 自定义Access配置
    
            // CSRF攻击拦截关闭
            httpSecurity.csrf().disable();
            httpSecurity.exceptionHandling().accessDeniedHandler(accessDeniedHandler);
    
    
            // 记住我
            httpSecurity.rememberMe().
                    tokenValiditySeconds(60). // 设置Token有效时间, 以秒为单位取值
                    userDetailsService(userDetailsService).
                    tokenRepository(persistentTokenRepository);
            
            // 退出登录处理
            httpSecurity.logout().logoutSuccessUrl("/login.html");
        }
    }

    如果需要配置独特的退出URL也可以设置:

    // 退出登录处理
    httpSecurity.
            logout().
            // logoutUrl("/xxx/xxx/logout").
            logoutSuccessUrl("/login.html");

     

  • 相关阅读:
    Java沉思录之重识String
    【python】 爬虫-爬取新闻
    【大数据】水质分析————(数据预处理)对水质图片的处理
    神经网络 鸢尾花数集预测
    【python 基础】词云
    【数据结构】字符串匹配
    【算法】 分治
    【数据结构】队列
    【数据结构】栈 的 顺序表示
    【数据结构】 线性表 的 链式存储结构
  • 原文地址:https://www.cnblogs.com/mindzone/p/13748014.html
Copyright © 2020-2023  润新知