拦截器session实现权限控制
·
拦截器:
- 自定义一个拦截器 继承
HandlerInterceptorAdapter - 将自定义拦截器添加到springmvc中,,实现
WebMvcConfigurer,,重写addInterceptors()
代码:
配置类:
@Component
public class AuthInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
/**
* request.getRequestURL() : 返回全路径 http://localhost:8080/project_name/user/login.do
* request.getRequestURI() : 返回除去协议和域名部分的路径 /project_name/user/login.do
*/
String requestURI = request.getRequestURI();
// 不需要登录就可以访问的路径
if (requestURI.contains(".") || requestURI.startsWith("/"+ MyConstant.RESOURCE_COMMON+"/")) {
return true;
}
// 未登录的用户 直接拒绝
if(request.getSession().getAttribute(MyConstant.FLAG_CURRENTUSER) == null){
response.setCharacterEncoding("utf-8");
response.getWriter().write("please login first");
return false;
}else {
// 登录的用户 判断他是否具备权限
UserBean currentUser = (UserBean) request.getSession().getAttribute(MyConstant.FLAG_CURRENTUSER);
if(requestURI.startsWith("/"+MyConstant.RESOURCE_MOBILE+"/") && currentUser.havePermission(MyConstant.RESOURCE_MOBILE)){
return true;
}else if(requestURI.startsWith("/"+MyConstant.RESOURCE_SALARY+"/") && currentUser.havePermission(MyConstant.RESOURCE_SALARY)){
System.out.println("===================================");
// 换个不存在的路径,满足这个条件,,也会走else 。。。 估计是抛异常,没有将true返回,, 为什么要走下面的else????
return true;
}else{
// 没得权限
response.setCharacterEncoding("utf-8");
response.getWriter().write("no auth to visit---");
return false;
}
}
}
}
@Component
public class MyWebAppConfigurer implements WebMvcConfigurer {
@Autowired
private AuthInterceptor authInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 配置拦截器 ,,除开error。。产生错误时,不走拦截器,直接返回
registry.addInterceptor(authInterceptor).addPathPatterns("/**").excludePathPatterns("/error");
}
}
实体类:
public class UserBean {
private String userId;
private String userName;
private String userPass;
private List<RoleBean> userRoles = new ArrayList<>();
private List<ResourceBean> resourcebeans = new ArrayList<>();
public UserBean(String userId, String userName, String userPass) {
this.userId = userId;
this.userName = userName;
this.userPass = userPass;
}
/**
* 是否有这个 资源 的权限
* @param resource 传入的资源
* @return
*/
public boolean havePermission(String resource){
return this.resourcebeans.stream().filter((resourceBean)->{
return resourceBean.getResourceName().equals(resource);
}).count() > 0;
}
public class RoleBean {
private String roleId;
private String roleName;
private List<ResourceBean> resources;
public RoleBean() {
}
public RoleBean(String roleId, String roleName) {
this.roleId = roleId;
this.roleName = roleName;
}
public class ResourceBean {
/**
* springsecurity 中 资源被简化成了一个字符串。。。
* 自己设计资源时,可以设计不同类型的资源控制不同的行为
* 控制菜单的资源,,,, 控制页面控件的资源,,,,控制某个接口的资源
*/
private String resourceId;
// 资源属性
private String resourceType;
// 资源名字
private String resourceName;
public ResourceBean() {
}
public ResourceBean(String resourceId, String resourceName) {
this.resourceId = resourceId;
this.resourceName = resourceName;
}
工具类:
public class MyConstant {
public static final String FLAG_CURRENTUSER="currentUser";
public static final String RESOURCE_COMMON="common";
public static final String RESOURCE_MOBILE="mobile";
public static final String RESOURCE_SALARY="salary";
}
/**
* 模拟的用户数据
*/
@Component
public class TestData {
private List<UserBean> allUser;
/**
* 模拟数据库得到的数据
* admin用户 具有admin角色 ,, 访问mobile,salary资源
* mobile用户 具有mobile角色,访问mobile资源
* worker用户 ,, 没有角色
* @return
*/
private List<UserBean> getAllUser(){
if(null == allUser){
allUser = new ArrayList<>();
// 模拟了两个资源
ResourceBean mobileResource = new ResourceBean("1", "mobile");
ResourceBean salaryResource = new ResourceBean("2", "salary");
// 两种资源权限
ArrayList<ResourceBean> adminResources = new ArrayList<>();
adminResources.add(mobileResource);
adminResources.add(salaryResource);
ArrayList<ResourceBean> managerResources = new ArrayList<>();
managerResources.add(salaryResource);
// admin 角色 可以访问 mobile 和 salary
RoleBean adminRole = new RoleBean("1", "admin");
adminRole.setResources(adminResources);
// manager 角色 只能访问 salary
RoleBean managerRole = new RoleBean("1", "manager");
managerRole.setResources(managerResources);
// admin 用户,,具备admin角色
UserBean admin = new UserBean("1", "admin", "admin");
admin.setUserRoles(Arrays.asList(adminRole));
admin.setResourcebeans(adminResources);
// manager用户 具备 manager角色
UserBean manager = new UserBean("2", "manager", "manager");
manager.setUserRoles(Arrays.asList(managerRole));
manager.setResourcebeans(managerResources);
// worker用户 ,,不具备角色
UserBean worker = new UserBean("3", "worker", "worker");
allUser.add(admin);
allUser.add(manager);
allUser.add(worker);
}
return allUser;
}
/**
* 校验user 是否有效
* @param user 传入的user
* @return
*/
public UserBean queryUser(UserBean user){
// 符合要求的user
List<UserBean> userList = this.getAllUser().stream().filter(userbean -> {
return userbean.getUserName().equals(user.getUserName()) && userbean.getUserPass().equals(user.getUserPass());
}).collect(Collectors.toList());
return userList.size()>0?userList.get(0):null;
}
}
controller:
/**
* 登录逻辑
*/
@RestController
@RequestMapping("/common")
public class LoginController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private AuthService authService;
@PostMapping("/login")
public UserBean login(UserBean loginUser, HttpServletRequest req){
// 如果验证成功,返回user
UserBean user = authService.userLogin(loginUser);
if(user != null){
logger.info("user login success");
req.getSession().setAttribute(MyConstant.FLAG_CURRENTUSER,user);
}else{
logger.info("user login failed");
}
return user;
}
@PostMapping("/getCurrentUser")
public Object getCurrentUser(HttpSession session){
return session.getAttribute(MyConstant.FLAG_CURRENTUSER);
}
@PostMapping("/logout")
public void logout(HttpSession session){
session.removeAttribute(MyConstant.FLAG_CURRENTUSER);
}
}
/**
* 代表一个 查手机 的后台接口
*/
@RestController
@RequestMapping("/mobile")
public class MobileController {
@GetMapping("/query")
public String query(){
return "mobile";
}
}
/**
* 代表一个 查薪水 的后台接口
*/
@RestController
@RequestMapping("/salary")
public class SalaryController {
@GetMapping("/query")
public String query(){
return "salary";
}
}
service:
/**
* 对用户进行检查的后台服务
*/
@Service
public class AuthService {
private final String demoUserName = "admin";
private final String demoUserPass = "admin";
@Autowired
TestData testData;
/**
* 判断这个user 是否存在
* @param user user
* @return
*/
public UserBean userLogin(UserBean user) {
// 查找是否有这个 user
UserBean userBean = testData.queryUser(user);
if(userBean != null){
userBean.setUserId(UUID.randomUUID().toString());
}
return userBean;
}
遇到的问题:
- 拦截器中springmvc访问404后,为什么不返回404内容,会去执行else逻辑
因为404报错后,返回的error页面,也被拦截器拦截执行else,,相当于拦截了两次
引用: https://blog.csdn.net/cainiao1412/article/details/124609024
https://blog.csdn.net/qq_39552993/article/details/120300799
更多推荐
所有评论(0)