普通用户也能访问管理员订单列表接口

普通用户也能访问管理员订单列表接口

问题描述:

以用户身份登录后再次请求订单列表接口(管理员用),也能返回数据


相关截图:

http://img1.sycdn.imooc.com//climg/6079529809ac588417411068.jpg

http://img1.sycdn.imooc.com//climg/607952ab09cfeb6017731093.jpg


OrderAdminController:

package com.fanyu.mall.controller;

import com.fanyu.mall.common.ApiRestResponse;
import com.fanyu.mall.service.OrderService;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/order")
public class OrderAdminController {
@Autowired
OrderService orderService;
@GetMapping("/admin/list")
@ApiOperation("后台查看订单列表")
public ApiRestResponse list(@RequestParam("pageNum") Integer pageNum, @RequestParam("pageSize") Integer pageSize) {
PageInfo pageInfo = orderService.listForAdmin(pageNum,pageSize);
return ApiRestResponse.success(pageInfo);
}
}

OrderServiceImpl:

package com.fanyu.mall.service.impl;

import com.fanyu.mall.common.Constant;
import com.fanyu.mall.exception.FanyuMallException;
import com.fanyu.mall.exception.FanyuMallExceptionEnum;
import com.fanyu.mall.filter.UserFilter;
import com.fanyu.mall.model.dao.OrderItemMapper;
import com.fanyu.mall.model.dao.OrderMapper;
import com.fanyu.mall.model.dao.ProductMapper;
import com.fanyu.mall.model.pojo.Order;
import com.fanyu.mall.model.pojo.OrderItem;
import com.fanyu.mall.model.pojo.Product;
import com.fanyu.mall.model.request.CreateOrderReq;
import com.fanyu.mall.service.OrderService;
import com.fanyu.mall.util.OrderCodeFactory;
import com.fanyu.mall.util.QRCodeGenerator;
import com.fanyu.mall.vo.CartVO;
import com.fanyu.mall.vo.OrderItemVO;
import com.fanyu.mall.vo.OrderVO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.zxing.WriterException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class OrderServiceImpl implements OrderService {

@Autowired
CartServiceImpl cartService;
@Autowired
ProductMapper productMapper;
@Autowired
OrderItemMapper orderItemMapper;
@Autowired
OrderMapper orderMapper;
@Value("${file.upload.ip}")
String ip;
//数据库事务
@Transactional(rollbackFor = Exception.class)
@Override
public String create(CreateOrderReq createOrderReq){
//获取userid
Integer userId = UserFilter.currentUser.getId();
//根据userID从购物车查询【勾选的】商品信息
List<CartVO> cartVOList = cartService.list(userId);
List<CartVO> selectedCartVOList = new ArrayList<>();
for (int i = 0; i < cartVOList.size(); i++) {
CartVO cartVO = cartVOList.get(i);
if(cartVO.getSelected().equals(Constant.selectedStatus.SELECTED)){
selectedCartVOList.add(cartVO);
}
}
cartVOList = selectedCartVOList;
//购物车中勾选的商品为空则报错
// if(cartVOList == null || cartVOList.size() == 0){
//CollectionUtils.isNotEmpty() 包含null,size=0等多种情况
//而== null 只能用来判断是否为null
if(CollectionUtils.isEmpty(cartVOList)){
throw new FanyuMallException(FanyuMallExceptionEnum.NO_SELECTED_PRODUCT);
}
//判断购物车对应存在商品,且状态可售,且库存数充足
validCartVOList(cartVOList);
//购物车对象转化为orderitem对象
List<OrderItem> orderItemList = cartVOListToOrderItemList(cartVOList);

//扣除库存
for (int i = 0; i < orderItemList.size(); i++) {
OrderItem orderItem = orderItemList.get(i);
Product product = productMapper.selectByPrimaryKey(orderItem.getProductId());
int count = product.getStock() - orderItem.getQuantity();
if(count < 0){
throw new FanyuMallException(FanyuMallExceptionEnum.NOT_ENOUGH);
}
product.setStock(count);
product.setUpdateTime(new Date());///////更新时间变化了
productMapper.updateByPrimaryKeySelective(product);
}
//将勾选的商品从购物车删除
flushCarts(userId,cartVOList);
//生成订单
Order order = new Order();
//设置订单各属性(未定的属性先不设置),尤其是订单号,关注如何生成
String orderNo = OrderCodeFactory.getOrderCode(Long.valueOf(userId));
order.setOrderNo(orderNo);
order.setUserId(userId);
order.setTotalPrice(totalPrice(orderItemList));//需要自己计算
order.setReceiverName(createOrderReq.getReceiverName());
order.setReceiverMobile(createOrderReq.getReceiverMobile());
order.setReceiverAddress(createOrderReq.getReceiverAddress());

order.setOrderStatus(Constant.OrderStatusEnum.NOT_PAID.getCode());//定义枚举类出错,先通过硬编码方式

order.setPostage(0);
order.setPaymentType(1);
//忘记插入了
orderMapper.insertSelective(order);
//将orderitemlist挨个插入到orderitem表里
for (int i = 0; i < orderItemList.size(); i++) {
OrderItem orderItem = orderItemList.get(i);
orderItem.setOrderNo(orderNo);
orderItemMapper.insertSelective(orderItem);
}
//返回生成的订单号
return orderNo;
}

private Integer totalPrice(List<OrderItem> orderItemList) {
Integer totalPrice = 0;
for (int i = 0; i < orderItemList.size(); i++) {
OrderItem orderItem = orderItemList.get(i);
totalPrice += orderItem.getTotalPrice();
}
return totalPrice;
}

private void flushCarts(Integer userId,List<CartVO> cartVOList) {
for (int i = 0; i < cartVOList.size(); i++) {
CartVO cartVO = cartVOList.get(i);
cartService.delete(userId,cartVO.getProductId());
}
}

private void validCartVOList(List<CartVO> cartVOList){
CartVO cartVOTemp;
Product productTemp;
for (int i = 0; i < cartVOList.size(); i++) {
cartVOTemp = cartVOList.get(i);
productTemp = productMapper.selectByPrimaryKey(cartVOTemp.getProductId());
//校验商品
if(productTemp == null || productTemp.getStatus().equals(Constant.saleStatus.NOT_SALE)){
throw new FanyuMallException(FanyuMallExceptionEnum.NOT_SALE);
}
//校验库存
if(cartVOTemp.getQuantity() > productTemp.getStock()){
throw new FanyuMallException(FanyuMallExceptionEnum.NOT_ENOUGH);
}
}


}
private List<OrderItem> cartVOListToOrderItemList(List<CartVO> cartVOList){
List<OrderItem> orderItemList = new ArrayList<>();
for (int i = 0; i < cartVOList.size(); i++) {
CartVO cartVO = cartVOList.get(i);
OrderItem orderItem = new OrderItem();
orderItem.setProductId(cartVO.getProductId());
//此时还未获取到orderNo未设置值
//保存此商品名称,价格,图片等的快照
orderItem.setProductImg(cartVO.getProductImage());
orderItem.setProductName(cartVO.getProductName());
orderItem.setQuantity(cartVO.getQuantity());
orderItem.setUnitPrice(cartVO.getPrice());
orderItem.setTotalPrice(cartVO.getTotalPrice());
orderItemList.add(orderItem);
}
return orderItemList;
}
@Override
public OrderVO detail(String orderNo){
//调用mapper根据orderNo查询出order对象
Order order = orderMapper.selectByOrderNo(orderNo);
//order对象是否存在
if(order == null){
throw new FanyuMallException(FanyuMallExceptionEnum.NO_ORDER);
}
//order对象存在的前提下判断订单所属人是否和当前登录人为同一人
Integer userId = UserFilter.currentUser.getId();
if(!userId.equals(order.getUserId())){
throw new FanyuMallException(FanyuMallExceptionEnum.NOT_YOUR_ORDER);
}
//子方法,根据order对象获得orderVO对象并返回
OrderVO orderVO = getOrderVOFromOrder(order);
return orderVO;
}

private OrderVO getOrderVOFromOrder(Order order) {
//copy共同属性从order到orderVO
OrderVO orderVO = new OrderVO();
BeanUtils.copyProperties(order,orderVO);

//为orderstatusname设置值
//codeOF方法的作用是根据code码获得这个枚举类对象
orderVO.setOrderStatusName(Constant.OrderStatusEnum.codeOf(order.getOrderStatus()).getMessage());

//根据orderNo获得此订单下的所有的orderitem的list
List<OrderItem> orderItemList = orderItemMapper.selectByOrderNo(order.getOrderNo());

//循环遍历该orderitemlist把每一个orderitem转换为orderitemvo,构成list
List<OrderItemVO> orderItemVOList = new ArrayList<>();
for (int i = 0; i < orderItemList.size(); i++) {
OrderItem orderItem = orderItemList.get(i);
OrderItemVO orderItemVO = new OrderItemVO();
BeanUtils.copyProperties(orderItem,orderItemVO);
orderItemVOList.add(orderItemVO);
}
// 为ordervo设置orderitemvo的list的值
orderVO.setOrderItemVOList(orderItemVOList);
//返回
return orderVO;

}
@Override
public PageInfo listForCustomer(Integer pageNum, Integer pageSize){
//获取到userid
Integer userId = UserFilter.currentUser.getId();
//设置pagehelper(在实际查询数据库操作的前一步)
PageHelper.startPage(pageNum,pageSize);
//查询order表里面与这个人关联的所有的order组成list
List<Order> orderList = orderMapper.selectByUserId(userId);
////////////////
System.out.println("orderServiceImpl.listForCustomer userId:" + userId + "返回的orderlist.size为" + orderList.size());
for (int i = 0; i < orderList.size(); i++) {
System.out.println(orderList.get(i));
}

////////////////////
//orderlist转换为ordervolist
List<OrderVO> orderVOList = orderListToOrderVOList(orderList);

//封装进pageinfo并返回
PageInfo pageInfo = new PageInfo(orderList);
pageInfo.setList(orderVOList);
return pageInfo;
}

private List<OrderVO> orderListToOrderVOList(List<Order> orderList) {
List<OrderVO> orderVOList = new ArrayList<>();
for (int i = 0; i < orderList.size(); i++) {
Order order = orderList.get(i);
OrderVO orderVO = getOrderVOFromOrder(order);
orderVOList.add(orderVO);
}
return orderVOList;
}
@Transactional(rollbackFor = Exception.class)
@Override
public void cancel(String orderNo){
//查询出order对象
Order order = orderMapper.selectByOrderNo(orderNo);
//判断是否为null
if(order == null){
throw new FanyuMallException(FanyuMallExceptionEnum.NO_ORDER);
}
//判断订单所属
Integer userId = UserFilter.currentUser.getId();
if(!userId.equals(order.getUserId())){
System.out.println("当前登录id:" + userId);
System.out.println("order所属user:" + order.getUserId());
throw new FanyuMallException(FanyuMallExceptionEnum.NOT_YOUR_ORDER);
}
//业务上只有未付款的订单可取消
if(!order.getOrderStatus().equals(Constant.OrderStatusEnum.NOT_PAID.getCode())){
throw new FanyuMallException(FanyuMallExceptionEnum.NEED_UNPAID);
}
//更新orderstatus和updatetime,endtime的值
order.setOrderStatus(Constant.OrderStatusEnum.CANCELED.getCode());
order.setUpdateTime(new Date());
order.setEndTime(new Date());
orderMapper.updateByPrimaryKeySelective(order);
//查询该订单对应的orderitem,循环遍历获得productid,更新product表updatetime和stock
List<OrderItem> orderItemList = orderItemMapper.selectByOrderNo(orderNo);
for (int i = 0; i < orderItemList.size(); i++) {
OrderItem orderItem = orderItemList.get(i);
Product product = productMapper.selectByPrimaryKey(orderItem.getProductId());
product.setStock(product.getStock() + orderItem.getQuantity());
product.setUpdateTime(new Date());
productMapper.updateByPrimaryKeySelective(product);
}
}
@Override
public String qrcode(String orderNo){
//引入生成二维码相关依赖
//util包下建生成二维码工具类QRCodeGenerator
//获取到和IP,port等相关的request信息***********难点
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes requestAttributes = (ServletRequestAttributes)attributes;
ServletRequest servletRequest = requestAttributes.getRequest();
//拼接组成二维码的URL
int port = servletRequest.getLocalPort();
String address = ip + ":" + port;
String payUrl = "http://" + address + "/pay?orderNo=" + orderNo;
//调用生成二维码接口
try {
QRCodeGenerator.generateQRCodeImage(payUrl,350,350,Constant.FILE_UPLOAD_DIR + orderNo + ".png");
} catch (WriterException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//返回的是访问这个二维码的URL地址
return "http://" + address + "/mall/images/" + orderNo + ".png";
}

@Override
public PageInfo listForAdmin(Integer pageNum, Integer pageSize){
// //获取到userid
// Integer userId = UserFilter.currentUser.getId();
//设置pagehelper(在实际查询数据库操作的前一步)
PageHelper.startPage(pageNum,pageSize);
//查询order表里面与这个人关联的所有的order组成list
List<Order> orderList = orderMapper.selectAllForAdmin();
////////////////
System.out.println("orderServiceImpl.listForAdmin:" + "返回的orderlist.size为" + orderList.size());
for (int i = 0; i < orderList.size(); i++) {
System.out.println(orderList.get(i));
}

////////////////////
//orderlist转换为ordervolist
List<OrderVO> orderVOList = orderListToOrderVOList(orderList);

//封装进pageinfo并返回
PageInfo pageInfo = new PageInfo(orderList);
pageInfo.setList(orderVOList);
return pageInfo;
}

}

UserFilter:

package com.fanyu.mall.filter;

import com.fanyu.mall.common.Constant;
import com.fanyu.mall.model.pojo.User;
import com.fanyu.mall.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

//普通用户校验过滤器
public class UserFilter implements Filter {
@Autowired
UserService userService;

public static User currentUser;


@Override
public void init(FilterConfig filterConfig) throws ServletException {
//无需实现
}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpSession session = request.getSession();
System.out.println("进来了userfilter===============");
currentUser = (User)session.getAttribute(Constant.FANYU_MALL_USER);
if(currentUser == null){
// return ApiRestResponse.error(FanyuMallExceptionEnum.NEED_LOGIN);
//不能这样返回,因为方法是固定的返回void
//可利用writer达到相同效果(还没进入controller之前所使用的的方法)
PrintWriter out = new HttpServletResponseWrapper((HttpServletResponse)servletResponse).getWriter();
out.write("{\n" +
" \"status\": 10007,\n" +
" \"msg\": \"NEED_LOGIN\",\n" +
" \"data\": null\n" +
"}");//内容就是我们想要返回的postman里的json数据
out.flush();
out.close();
return;//方法执行到此已结束,不会进入到后续的过滤器或者controller层
}

//放行,即校验通过,会进入后续
filterChain.doFilter(servletRequest,servletResponse);

}

@Override
public void destroy() {
//无需实现
}
}

UserFilterConfig:

package com.fanyu.mall.config;

import com.fanyu.mall.filter.UserFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class UserFilterConfig {

//1.先定义出来这个filter
@Bean
public UserFilter userFilter(){
return new UserFilter();
}

//2.把这个filter放到链路中
@Bean(name = "userFilterConf")
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
//为过滤器配置设置过滤器
filterRegistrationBean.setFilter(userFilter());
//为过滤器配置设置过滤URL
filterRegistrationBean.addUrlPatterns("/cart/*");
filterRegistrationBean.addUrlPatterns("/order/*");
//为过滤器配置设置名字,以区分不同的配置
//注意这个名字不能设置成和此类一样,否则这两个bean就冲突了
filterRegistrationBean.setName("userFilterConf");
// filterRegistrationBean.setOrder(2);
return filterRegistrationBean;
}
}

AdminFilter:

package com.fanyu.mall.filter;

import com.fanyu.mall.common.Constant;
import com.fanyu.mall.model.pojo.User;
import com.fanyu.mall.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

//管理员校验过滤器
public class AdminFilter implements Filter {
@Autowired
UserService userService;


@Override
public void init(FilterConfig filterConfig) throws ServletException {
//无需实现
}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpSession session = request.getSession();
System.out.println("进来了adminfilter===============");
User currentUser = (User)session.getAttribute(Constant.FANYU_MALL_USER);
if(currentUser == null){
// return ApiRestResponse.error(FanyuMallExceptionEnum.NEED_LOGIN);
//不能这样返回,因为方法是固定的返回void
//可利用writer达到相同效果(还没进入controller之前所使用的的方法)
PrintWriter out = new HttpServletResponseWrapper((HttpServletResponse)servletResponse).getWriter();
out.write("{\n" +
" \"status\": 10007,\n" +
" \"msg\": \"NEED_LOGIN\",\n" +
" \"data\": null\n" +
"}");//内容就是我们想要返回的postman里的json数据
out.flush();
out.close();
return;//方法执行到此已结束,不会进入到后续的过滤器或者controller层
}
System.out.println("当前用户是:" + currentUser.getUsername() + "身份是" + currentUser.getRole());
boolean adminRole = userService.checkAdminRole(currentUser);

if(adminRole){
//放行,即校验通过,会进入后续
System.out.println("是管理员开始放行***************");
filterChain.doFilter(servletRequest,servletResponse);
}else {
System.out.println("不是管理员进行拦截***************");
PrintWriter out = new HttpServletResponseWrapper((HttpServletResponse)servletResponse).getWriter();
out.write(" {\n" +
" \"status\": 10009,\n" +
" \"msg\": \"NEED_ADMIN\",\n" +
" \"data\": null\n" +
"}");//内容就是我们想要返回的postman里的json数据
out.flush();
out.close();
return;//方法执行到此已结束,不会进入到后续的过滤器或者controller层(这一个return也可以不加)

}
}

@Override
public void destroy() {
//无需实现
}
}

AdminFilterConfig:

package com.fanyu.mall.config;

import com.fanyu.mall.filter.AdminFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AdminFilterConfig {

//1.先定义出来这个filter
@Bean
public AdminFilter adminFilter(){
return new AdminFilter();
}

//2.把这个filter放到链路中
@Bean(name = "adminFilterConf")
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
//为过滤器配置设置过滤器
filterRegistrationBean.setFilter(adminFilter());
//为过滤器配置设置过滤URL
filterRegistrationBean.addUrlPatterns("/admin/category/*");
filterRegistrationBean.addUrlPatterns("/admin/product/*");
filterRegistrationBean.addUrlPatterns("/admin/order/*");
//为过滤器配置设置名字,以区分不同的配置
//注意这个名字不能设置成和此类一样,否则这两个bean就冲突了
filterRegistrationBean.setName("adminFilterConf");
//filterRegistrationBean.setOrder(1);
return filterRegistrationBean;
}
}


正在回答

登陆购买课程后可参与讨论,去登陆

2回答

同学你好,这两个过滤器拦截的url不重合,/admin/order/*拦截的是后台订单的url,而/order/*拦截的是前台订单的url,拦截的内容不重叠,如:

后台拦截的url,如:

http://img1.sycdn.imooc.com//climg/607a453c0981559407960187.jpg

http://img1.sycdn.imooc.com//climg/607a45550950049407550163.jpg

前台拦截的url:

http://img1.sycdn.imooc.com//climg/607a45750902741207610172.jpg

http://img1.sycdn.imooc.com//climg/607a45880992cdc209600180.jpg

祝学习愉快~

  • cloudonthesun 提问者 #1

    好的,谢谢老师

    2021-04-18 09:37:07
好帮手慕阿满 2021-04-16 18:55:13

同学你好,同学后台查看订单列表的url是/admin/list,如:

http://img1.sycdn.imooc.com//climg/60796c2109ad153103640134.jpg

而在AdminFilterConfig中对订单进行拦截的url是/admin/order/*,如:

http://img1.sycdn.imooc.com//climg/60796bff09b7e18b06660296.jpg

同学/admin/list不在管理员过滤器拦截的范围内,所以普通用户可以访问订单列表。

这里应该按照管理员过滤器的url来写,这样才能被拦截,判断是否是管理员登录,是否有权限查看订单列表,如:

http://img1.sycdn.imooc.com//climg/60796d0c0999b3f808000185.jpg

祝学习愉快~

  • 提问者 cloudonthesun #1

    好的,老师,已更改,另外还有一个问题,

    http://img1.sycdn.imooc.com//climg/60797c1b09465e6715180525.jpg

    http://img1.sycdn.imooc.com//climg/60797c3309be220515020607.jpg


    这两个filter过滤的URL是不是有重合的部分,当访问127.0.0.1:8080/mall/admin/order/list?pageNum=1&pageSize=3

    时,这两个过滤器都会过滤吗,过滤顺序是怎样的呢

    我看只有adminfilter过滤器进行过滤了

    http://img1.sycdn.imooc.com//climg/60797e0309e7a94821610702.jpg

    2021-04-16 20:08:50
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师