package org.apereo.cas.otp.web.flow.rest; import com.google.common.base.Throwables; import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.QRCodeWriter; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import javax.imageio.ImageIO; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.awt.Color; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.util.EnumMap; import java.util.Map; import java.util.stream.IntStream; /** * This is {@link OneTimeTokenQRGeneratorController}. * * @author Misagh Moayyed * @since 5.0.0 */ @RestController public class OneTimeTokenQRGeneratorController { /** * Generate. * * @param response the response * @param request the request * @throws Exception the exception */ @GetMapping(path = {"/otp/qrgen"}) public void generate(final HttpServletResponse response, final HttpServletRequest request) throws Exception { response.setContentType("image/png"); final String key = request.getParameter("key"); generateQRCode(response.getOutputStream(), key); } private static void generateQRCode(final OutputStream stream, final String key) { try { final Map<EncodeHintType, Object> hintMap = new EnumMap<>(EncodeHintType.class); hintMap.put(EncodeHintType.CHARACTER_SET, StandardCharsets.UTF_8.name()); hintMap.put(EncodeHintType.MARGIN, 2); hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); final QRCodeWriter qrCodeWriter = new QRCodeWriter(); final BitMatrix byteMatrix = qrCodeWriter.encode(key, BarcodeFormat.QR_CODE, 250, 250, hintMap); final int width = byteMatrix.getWidth(); final BufferedImage image = new BufferedImage(width, width, BufferedImage.TYPE_INT_RGB); image.createGraphics(); final Graphics2D graphics = (Graphics2D) image.getGraphics(); try { graphics.setColor(Color.WHITE); graphics.fillRect(0, 0, width, width); graphics.setColor(Color.BLACK); IntStream.range(0, width) .forEach(i -> IntStream.range(0, width) .filter(j -> byteMatrix.get(i, j)) .forEach(j -> graphics.fillRect(i, j, 1, 1))); } finally { graphics.dispose(); } ImageIO.write(image, "png", stream); } catch (final Exception e) { throw Throwables.propagate(e); } } }