数据库中的数据
com.itheima.security.controller.UserController
package com.itheima.security.controller;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.security.PermitAll;
/**
* @author by itheima
* @Date 2022/1/22
* @Description
*/
@RestController
public class UserController {
@PreAuthorize("hasAnyAuthority('P1','P5')")
@GetMapping("/hello")
public String hello() {
return "hello security";
}
//{"username":"itheima","password":"123456"}
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/say")
public String say() {
return "say security";
}
@PermitAll
@GetMapping("/register")
public String register() {
return "register security";
}
}
itcast用户可以访问/say和/hello接口,itheima用户可以访问/hello,没有权限访问/say
不携带token,也就是游客(未登录用户)访问
注意用Postwoman测试的时候要禁用缓存,不然会有实际访问的用户变成缓存的用户访问的情况
可以看到游客和已经登录但是对某些资源没有权限的用户访问返回的都是相同的响应,不便于用户体验,现在针对不同类型的访问,响应不同的内容,给用户相应的提示
新建com.itheima.security.handler.MyAccessDenyHandler
package com.itheima.security.handler;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.MediaType;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* 用户无权限访问,访问拒绝的处理器
*/
public class MyAccessDenyHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding("UTF-8");
Map<String, String> info = new HashMap<>();
info.put("msg", "无权限访问");
info.put("code", "0");
info.put("data", "");
response.getWriter().write(new ObjectMapper().writeValueAsString(info));
}
}
在SecurityConfig类中配置处理器
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().and().logout().permitAll().and().csrf().disable().
authorizeRequests();
//将自定义过滤器加入过滤器链并在默认的过滤器的前面执行
http.addFilterBefore(myUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
//配置授权过滤器,为了保证资源安全,给与最高优先级,在自定义认证过滤器之前执行
http.addFilterBefore(authenticationFilter(), MyUsernamePasswordAuthenticationFilter.class);
//配置拒绝处理器
http.exceptionHandling().accessDeniedHandler(new MyAccessDenyHandler());
//http.exceptionHandling().accessDeniedHandler(new MyAccessDenyHandler()).authenticationEntryPoint(new MyAuthenticationEntryPoint());
}
测试一下
新建匿名用户访问拒绝处理器com.itheima.security.handler.MyAuthenticationEntryPoint
package com.itheima.security.handler;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* 匿名用户访问拒绝的处理器
*/
public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding("UTF-8");
Map<String, String> info = new HashMap<>();
info.put("msg", "未登录访问");
info.put("code", "0");
info.put("data", "");
response.getWriter().write(new ObjectMapper().writeValueAsString(info));
}
}
配置一下
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().and().logout().permitAll().and().csrf().disable().
authorizeRequests();
//将自定义过滤器加入过滤器链并在默认过滤器的前面执行
http.addFilterBefore(myUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
//配置授权过滤器,为了保证资源安全,给与最高优先级,在自定义认证过滤器之前执行
http.addFilterBefore(authenticationFilter(), MyUsernamePasswordAuthenticationFilter.class);
//配置无权限访问拒绝处理器
//http.exceptionHandling().accessDeniedHandler(new MyAccessDenyHandler());
//配置无权限访问处理器和匿名用户访问拒绝处理器
http.exceptionHandling().accessDeniedHandler(new MyAccessDenyHandler()).authenticationEntryPoint(new MyAuthenticationEntryPoint());
}
测试一下