C'est le 17e jour du Calendrier de l'avent de l'ingénieur système 2016.
Le 16ème jour était les [Points lors de l'application du SPA localement dans des applications Web non SPA] de M. Uga (http://qiita.com/uggds/items/1baf844e8fb1dc7c4b09). C'était un contenu d'actualité auquel j'ai immédiatement voulu me référer dans le prochain projet!
Lorsque vous souhaitez acheminer la valeur à l'écran pour enregistrer quelque chose, l'incorporer dans le champ masqué et la valeur correspond-elle au moment de l'enregistrement? Je pense que je vais le vérifier.
Par exemple, supposons que vous ayez une application comme soumettre en sélectionnant une catégorie, en ouvrant un nouvel écran de création de problème, en écrivant du contenu.
⬇︎
⬇︎
Sur l'écran d'inscription, intégrez l'ID de catégorie dans le champ masqué.
<input type="text" name="content"/>
<input type="hidden" name="categoryId" data-th-value="${category.id}"/>
<button type="submit">Save</button>
Le processus d'enregistrement [vérifie si cette valeur existe dans la table des catégories](https://github.com/backpaper0/seac2016/blob/no-hmac/src/main/java/com/example/IssueController. java # L50).
@PostMapping("new")
String post(@RequestParam String content, @RequestParam Long categoryId) {
//Contrôle d'existence à nouveau au moment de l'inscription
categoryDao.selectById(categoryId).orElseThrow(BadRequest::new);
Issue entity = new Issue();
entity.content = content;
entity.categoryId = categoryId;
issueDao.insert(entity);
return "redirect:/";
}
Cette vérification semble un peu surchargée car j'accède à la base de données, et j'ai toujours pensé que ce serait gênant s'il y avait plus de valeurs à vérifier. Généralement, lorsque l'écran d'enregistrement est affiché, la valeur obtenue en recherchant la catégorie est intégrée, mais pourquoi dois-je vérifier l'existence même dans le processus d'enregistrement! Je me sens comme.
Cependant, si vous réécrivez le code HTML, vous pouvez soumettre des valeurs qui sont impossibles et vous devez les vérifier correctement.
J'ai donc pensé à vérifier la valeur en utilisant HMAC.
Un hachage avec une clé. Même si vous connaissez la valeur, vous ne pouvez pas obtenir la valeur de hachage sans connaître la clé. De plus, même si vous hachez la même valeur, vous obtiendrez des valeurs de hachage différentes si les clés sont différentes. Pour plus d'informations, rendez-vous sur Gugu.
Modifiez la partie où le contrôle d'existence de la catégorie a été effectué en accédant au DB au contrôle à l'aide de HMAC.
Tout d'abord, lors de l'ouverture de l'écran d'enregistrement, [Hash category ID with HMAC](https://github.com/backpaper0/seac2016/blob/hmac-verify/src/main/java/com/example/IssueController.java# L47) puis Incorporer cette valeur dans la vue.
@GetMapping("new")
String blank(Model model, @RequestParam Long categoryId) throws GeneralSecurityException {
//Vérification d'existence de catégorie
Category category = categoryDao.selectById(categoryId).orElseThrow(BadRequest::new);
//Faites un hachage et intégrez-le dans le champ caché
String hash = verifier.hash(categoryId);
model.addAttribute("category", category);
model.addAttribute("hash", hash);
return "new-issue";
}
<input type="text" name="content"/>
<input type="hidden" name="categoryId" data-th-value="${category.id}"/>
<input type="hidden" name="hash" data-th-value="${hash}"/>
<button type="submit">Save</button>
Le traitement du hachage ressemble à ceci.
public String hash(Long value) throws GeneralSecurityException {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(key);
byte[] hash = mac.doFinal(String.valueOf(value).getBytes());
return IntStream.range(0, hash.length).mapToObj(i -> String.format("%02x", hash[i]))
.collect(Collectors.joining());
}
Dans le processus d'enregistrement, Hachez l'ID de catégorie soumis avec HMAC et comparez-le avec la valeur de hachage soumise /java/com/example/IssueController.java#L60).
if (verifier.verify(hash, categoryId) == false) {
throw new BadRequest();
}
Vous avez maintenant une vérification pour empêcher la valeur d'être modifiée, tout comme la vérification d'existence.
À propos, s'il y a plusieurs valeurs, si vous connectez toutes les valeurs avec :
ou .
et hash, vous n'avez besoin que d'une valeur de hachage, de sorte que la charge utile de la requête / réponse HTTP ne gonfle pas.
Comme il ne s'agit pas d'un contrôle d'existence strict, une incohérence se produira si la catégorie qui était présente lorsque l'écran d'enregistrement est affiché disparaît pendant le processus d'enregistrement. (Bien que cela soit empêché par la contrainte clé étrangère
dans l'exemple)
Par conséquent, vous devez faire attention à ne l'appliquer qu'aux données qui ne changent pas au cours de la journée (par exemple, département dans le cas d'un système d'entreprise).
En outre, pour les raisons mentionnées ci-dessus, vous souhaiterez peut-être invalider la valeur de hachage au fil des jours. Dans ce cas, Hash the date together est recommandé. De cette façon, si vous hachez les horodatages ensemble, vous pouvez avoir une date d'expiration, et si vous hachez chaque ID de session ensemble, vous pouvez créer un hachage valide pour chaque utilisateur.
Une autre mise en garde est la gestion des clés. Vous pouvez obtenir une valeur aléatoire lorsque vous démarrez l'application et l'utilisez comme clé, mais si vous avez plusieurs instances de l'application dans une configuration redondante, vous devez activer les sessions persistantes ou partager la clé entre toutes les instances. il y a. Je pense que ce type de gestion se fait au cas par cas.
J'ai réfléchi à la façon d'utiliser HMAC pour vérifier la validité de la valeur intégrée dans le champ caché. Il y a quelques mises en garde, mais je pense qu'il y a de nombreuses situations où cela peut être appliqué.
Un exemple de code est disponible sur GitHub.
No-hmac vérification de l'existence d'une branche à l'aide de la base de données, [hmac-verify](https: // s) vérification avec HMAC //github.com/backpaper0/seac2016/tree/hmac-verify) Branch, puis mélangez la date dans le hachage pour définir la date d'expiration master Il y a des succursales, alors comparez-les.
Ci-dessus ⛄️
Recommended Posts