拦截器:

  1. 自定义一个拦截器 继承 HandlerInterceptorAdapter
  2. 将自定义拦截器添加到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
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐