springboot学习之十四(SpringSecurity整合Thymeleaf和后台的权限注解)

1.首先,我们需要在pom文件中添加以下依赖:

<!--thymeleaf springsecurity5 依赖-->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<!--thymeleaf依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

 

2.在html页面中引入thymeleaf命名空间和security命名空间。

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extrasspringsecurity5">

 

3.获取属性:我们可以在html页面中通过sec:authentication标签获取usernamePasswordAuthenticationToken中所有getXXX的内容

name :登录账号名称
principal :登录主体,在自定义登录逻辑中是 UserDetails
credentials :凭证
authorities :权限和角色
details :实际上是 WebAuthenticationDetails 的实例。可以获取 remoteAddress (客
户端 ip)和 sessionId (当前 sessionId)

4.sec:authorize可以判断是否含有某权限或角色来显示或隐藏内容,做到权限的安全。

比如:
我们给用户添加以下角色和权限 (后台
UserDetailsServiceImpl的loadUserByUsername方法

//1.按照用户名查用户
//2.按id查权限list
//3.按id查角色list (角色必须前面拼接ROLE_)
//4.把权限list和角色list拼接成一个list,传入User
//User user=new User(username,myUser.getPassword(),authorities);

return new User("admin", encode,
                AuthorityUtils.commaSeparatedStringToAuthorityList("admin," +
                        "normal,ROLE_abc,/main.html, /insert, /delete"));

然后,在前端模板中写以下代码来判断权限和角色

<!--如果没认证-->
<div sec:authorize="!isAuthenticated()">显示没认证的内容</div>
<!--如果认证了-->
<div sec:authorize="isAuthenticated()">显示认证的内容</div>

通过权限判断:
<button sec:authorize="hasAuthority('/insert')">新增</button>
<button sec:authorize="hasAuthority('/delete')">删除</button>
<button sec:authorize="hasAuthority('/update')">修改</button>
<button sec:authorize="hasAuthority('/select')">查看</button>
<br/>
通过角色判断:
<button sec:authorize="hasRole('abc')">新增</button>
<button sec:authorize="hasRole('abc')">删除</button>
<button sec:authorize="hasRole('abc')">修改</button>
<button sec:authorize="hasRole('abc')">查看</button>

 

 

5.SpringSecurity的后台常用注解

 

@Secured注解 :@Secured注解用于校验用户具有某个角色,才可以访问方法

启动类上开启注解

@EnableGlobalMethodSecurity(securedEnabled = true)

方法上使用注解

/**
 * 测试@Secured注解
 * @return
*/
@RequestMapping("/add")
@Secured({"ROLE_student"})
public String add(){
    return "hello student!";
}

// 主体没有ROLE_teacher角色不能访问这个方法
@RequestMapping("/add2")
@Secured({"ROLE_teacher"})
public String add2(){
    return "hello teacher!";
}

登录是用户对象中设置角色(上面讲过)

@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
    List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("admin,ROLE_student");//权限和角色(角色前面加ROLE_)
    //可以从数据库获取用户名和密码
    return new User("qfAdmin",new BCryptPasswordEncoder().encode("123456"),auths);
}

 

@PreAuthorize :进入方法前的权限验证

启动类开启注解 

@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)

方法上使用注解

@RequestMapping("/postItems")
@PostAuthorize("hasAnyAuthority('teacher')")
public String postItems(){
    //先执行方法内容,再做权限校验
    System.out.println("show detail here...");
    return "show post items";
}

 

 @PostAuthorize :在方法访问之后进行校验,实际使用并不多

启动类上开启注解

@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)

方法上使用注解

@RequestMapping("/postItems")
@PostAuthorize("hasAnyAuthority('teacher')")
public String postItems(){
    //先执行方法内容,再做权限校验
    System.out.println("show detail here...");
    return "show post items";
}

 

@PostFilter : 权限验证之后对数据进行过滤,只能获取满足条件的数据

实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Long id;
    private String userName;
}

在方法上使用注解

@RequestMapping("/postFilterItems")
@PreAuthorize("hasAnyAuthority('admin')")
@PostFilter("filterObject.userName == 'xiaoming'")
public List<User> getUsers(){
    ArrayList<User> list = new ArrayList<User>();
    list.add(new User(1L,"xiaowang"));
    list.add(new User(2L,"xiaoming"));
    return list;
}
  • 访问接口,发现list集合中获取了满足条件的xiaoming对象

 

@PreFilter : 对传入方法的数据进行过滤

在方法上使用注解

@RequestMapping("/preFilterItems")
@PreAuthorize("hasAnyAuthority('admin')")
@PreFilter(value = "filterObject.userName == 'xiaoming'")
public List<User> getUsersByPreFilter(@RequestBody List<User> list) {
    //只有userName是'xiaoming'的数据才会被传入
    list.forEach(t -> {
        System.out.println(t.getUserName());
    });
    return list;
}
  • 访问方法,发现只有userName是’xiaoming’的数据才会被传入

 

 

6.注销页面

@Override
protected void configure(HttpSecurity http) throws Exception {
    //注销的配置
    http.logout().logoutUrl("/logout") //注销时访问的路径
        .logoutSuccessUrl("/logoutSuccess").permitAll(); //注销成功后访问的路径

    //配置没有权限的跳转页面
    http.exceptionHandling().accessDeniedPage("/error.html");
    
    http.formLogin()
        .loginPage("/login.html") //设置自定义登陆页面
        .loginProcessingUrl("/usr/login") //登陆时访问的路径
        //.defaultSuccessUrl("/index").permitAll() //登陆成功后跳转的路径
        .defaultSuccessUrl("/success.html").permitAll() //登陆成功后跳转的路径
        .and().authorizeRequests()
        .antMatchers("/","/add","/user/login").permitAll() //设置可以直接访问的路径,取消拦截
        //1.hasAuthority方法:当前登陆用户,只有具有admin权限才可以访问这个路径
        //.antMatchers("/index").hasAuthority("admin")
        //2.hasAnyAuthority方法:当前登陆用户,具有admin或manager权限可以访问这个路径
        //.antMatchers("/index").hasAnyAuthority("admin,manager")
        //3.hasRole方法:当前主体具有指定角色,则允许访问
        //.antMatchers("/index").hasRole("student")
        //4.hasAnyRole方法:当前主体只要具备其中某一个角色就能访问
        .antMatchers("/index").hasAnyRole("student1,teacher")
        .anyRequest().authenticated()
        .and().csrf().disable(); //关闭csrf防护
}

 

    @RequestMapping(value="/logout", method = RequestMethod.GET)
    public String logoutPage (HttpServletRequest request, HttpServletResponse response) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null){
            new SecurityContextLogoutHandler().logout(request, response, auth);
        }
        return "redirect:/login?logout";//You can redirect wherever you want, but generally it's a good practice to show login screen again.
    }

 

 

 

转 : https://blog.csdn.net/qq_42582773/article/details/121941391

https://blog.csdn.net/weixin_46818691/article/details/126630085

 https://blog.csdn.net/vbirdbest/article/details/90553444

posted @ 2023-07-25 11:01  与f  阅读(391)  评论(0编辑  收藏  举报