۱۴۰۰ آذر ۴, پنجشنبه

گرفتن IP کاربر در Spring Boot

به دلیل امنیتی، لازم که بتونیم IP کاربران رو ثبت کنیم. در یک برنامه معمولی Spring Boot مستقیما با کاربران تعامل دارد (بدون پراکسی، لود بالانس و غیره)، می‌توانیم به راحتی با استفاده متد getRemoteHost() از HttpServletRequest اقدام به گرفتن IP کاربران کنیم.

اما در بیشتر موارد، باید اپلیکیشن را پشت Nginx یا آپاچی قرار دهیم و درخواست ها رو به اپلیکیشن بفرستیم‌. در این حالت HttpServletRequest.getRemoteHost() آدرس IP پراکسی سرور را برمی‌گرداند. در نتیجه ما باید IP کاربران را در هدر درخواست ها ست کنیم. معمولا X-FORWARDED-FOR برای این منظور استفاده میشود، ولی تنها این گزینه نیست:

  • X-Forwarded-For
  • Proxy-Client-IP
  • WL-Proxy-Client-IP
  • HTTP_X_FORWARDED_FOR
  • HTTP_X_FORWARDED
  • HTTP_X_CLUSTER_CLIENT_IP
  • HTTP_CLIENT_IP
  • HTTP_FORWARDED_FOR
  • HTTP_FORWARDED
  • HTTP_VIA
  • REMOTE_ADDR

این گزینه ها را در فایل properties اپلیکیشن قرار می‌دهیم و سپس به راحتی، مانند کد پایین، میتوانیم آنها را چک کنیم:


application:
  header-ip-candidates: X-Forwarded-For,Proxy-Client-IP,WL-Proxy-Client-IP,HTTP_X_FORWARDED_FOR,HTTP_X_FORWARDED,HTTP_X_CLUSTER_CLIENT_IP,HTTP_CLIENT_IP,HTTP_FORWARDED_FOR,HTTP_FORWARDED,HTTP_VIA,REMOTE_ADDR

@RestController
@RequestMapping("/ip")
public class IPResource {

    @Value("${application.header-ip-candidates}")
    private String[] headerCandidates;

    @GetMapping
    public ResponseEntity getHome() {
        if (RequestContextHolder.getRequestAttributes() == null) {
            return ResponseEntity.ok("0.0.0.0");
        }

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        for (String header: headerCandidates) {
            String ipList = request.getHeader(header);
            if (ipList != null && ipList.length() != 0 && !"unknown".equalsIgnoreCase(ipList)) {
                String ip = ipList.split(",")[0];
                return ResponseEntity.ok(ip);
            }
        }
        return ResponseEntity.ok(request.getRemoteAddr());
    }
}

۱۴۰۰ آبان ۲۸, جمعه

تبدیل فایل به base64 در سمت کلاینت با VueJS

آپلود فایل از سمت کلاینت به سرور، یک تسک عادی است. تقریبا همه دولپر ها آنرا انجام دادند. پست کردن فایل با استفاده از نوع درخواست form data یک راه حل عادی است. ولی اگه بخواهیم یک عکس رو قبل از آپلود به سرور به کاربر نمایش بدیم باید چکار کنیم؟ یک باکس برای نمایش تصویر داریم و می‌خواهیم کاربر قبل از ذخیره و ارسال فایل به سرور بتواند تصویر انتخابی خودش را در آن ببیند.

من یک راه حل بر مبنای base64 پیدا کردم. بدینصورت که تصویر رو به base64 تبدیل کنم و سپس آنرا در یک متغیر ذخیره کنم و این متغیر را به باکس تصویر وصل کنم. البته می‌توانیم مقدار base64 را هم به سرور ارسال کنیم و آنجا آنرا به فرمت باینری تبدیل و ذخیره کنیم!

در VueJS، من از watch برای مانیتور کردن تغییرات روی فیلد انتخاب فایل استفاده میکنم تا بعد از تغییر از طرف کاربر، در اپ کلاینت، تصویر را به base64 تبدیل و در یک متغیر دیگر که به باکس تصویر وصل است، ذخیره میکنم.

اجازه بدهید آنها را در کد بررسی کنیم. در قدم اول من دو متغیر تعریف میکنم:

  1. image: متصل شده به فیلد انتخاب فایل
  2. base64: برای نگهداری نتیجه تبدیل 
سپس یک watch روی متغیر image برای بروز کردن base64، تعریف میکنم:


    image: function (newVal, oldVal) {
      if(newVal) {
        this.createBase64Image(newVal);
      } else {
        this.base64 = null;
      }
    }

در انتها، یک تابع برای تبدیل تصویر به base64 و بروزرسانی متغیر آن تعریف میکنم:


    createBase64Image: function(FileObject) {
      const reader = new FileReader();
      reader.onload = (event) => {
        this.base64 = event.target.result;
      }
      reader.readAsDataURL(FileObject);
    }

برای بررسی یک نمونه آنلاین میتوانید لینک https://codepen.io/glinboy/pen/KKvEzjy را چک کنید :)

۱۴۰۰ آبان ۲۷, پنجشنبه

سطر های کلیک شونده با ستونهایی که مستثتا هستند در VueJS

 به تجربه، ترجیح میدم سطرهای جدول قابل کلیک کردن باشند تا اینکه یک دکمه اضافه برای اینکار در آخرین ستون داشته باشم. در VueJS به راحتی میتوانیم @click را به تگ <tr> اضافه کنیم، مانند زیر

اما با دکمه های ستون آخر باید چکار کنیم؟ بعنوان مثال، اگر یک دکمه برای حذف و یک دکمه برای ویرایش داشته باشیم که کاربران مان راحتتر با جدول داده ها کار کنند.

بعد از یک جستجوی نسبتا طولانی، متوجه شدم که میتوانیم به راحتی از تگ @click.stop در تگ <td> استفاده کنیم، که در نتیجه آن دکمه ها میتوانند تابع مدنظرشان را اجرا کنند:

میتوانید آدرس https://codepen.io/glinboy/pen/YzxBQEN را بررسی کنید.