(Quick Reference)

14 セキュリティ - Reference Documentation

Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith

Version: 2.3.0

Translated by: T.Yamamoto, Japanese Grails Doc Translating Team. Special thanks to NTT Software.
【注意】このドキュメントの内容はスナップショットバージョンを元に*意訳*されているため、一部現行バージョンでは未対応の機能もあります。

14 セキュリティ

Grails is no more or less secure than Java Servlets. However, Java servlets (and hence Grails) are extremely secure and largely immune to common buffer overrun and malformed URL exploits due to the nature of the Java Virtual Machine underpinning the code.
Grailsは、Javaサーブレットと同等にセキュアであり、Javaサーブレットと比べてどちらが安全、というものではありません。とは言え、Javaサーブレット(そしてGrails)は、コードを支えるJava仮想マシンの性質によって極めて安全で、一般的なバッファオーバーランや不正な形式のURLエクスプロイトに対して、多くの場合影響を受けません。

Web security problems typically occur due to developer naivety or mistakes, and there is a little Grails can do to avoid common mistakes and make writing secure applications easier to write.
Web上でのセキュリティ問題は、開発者の知識の無さやうっかりミスにより起こることが多いでしょう。そこで、よくあるミスを防ぎ、安全なアプリケーションとしてよりコーディングしやすくするために、Grailsでは次のようなちょっとした機能を提供します。

h4. What Grails Automatically Does

Grailsが自動的に行うこと

Grails has a few built in safety mechanisms by default.
Grailsには、安全性を保つためデフォルトでいくつかのメカニズムが内蔵されています。

  1. All standard database access via GORM domain objects is automatically SQL escaped to prevent SQL injection attacks
  2. The default scaffolding templates HTML escape all data fields when displayed
  3. Grails link creating tags (link, form, createLink, createLinkTo and others) all use appropriate escaping mechanisms to prevent code injection
  4. Grails provides codecs to let you trivially escape data when rendered as HTML, JavaScript and URLs to prevent injection attacks here.

  1. GORM経由でのすべての標準的なデータベースアクセスにおける、SQLインジェクション攻撃を防ぐための自動的なエスケープ処理
  2. デフォルトのスカッフォルドテンプレートのHTMLにおける、すべてのデータフィールドに対する表示時のエスケープ処理
  3. Grailsのリンク作成タグ(linkformcreateLinkcreateLinkTo他)における、コードインジェクションを防ぐための適切なエスケープ機構
  4. GrailsでHTML、JavaScript、URLをレンダリングする際の、データを手軽にエスケープ処理しインジェクション攻撃を防ぐコーデックの提供

14.1 攻撃からの防御

h4. SQL injection

SQLインジェクション

Hibernate, which is the technology underlying GORM domain classes, automatically escapes data when committing to database so this is not an issue. However it is still possible to write bad dynamic HQL code that uses unchecked request parameters. For example doing the following is vulnerable to HQL injection attacks:
GORMドメインクラスの基盤であるHibernateは、データベースにコミットする際に自動的にデータをエスケープ処理するので、これは問題にはならないでしょう。しかしながら、未チェックなリクエストパラメータを用いた、よくない動的HQLコードを書いてしまうこともできてしまいます。例えば、以下のようなコードはHQLインジェクション攻撃に対して脆弱です:

def vulnerable() {
    def books = Book.find("from Book as b where b.title ='" + params.title + "'")
}

or the analagous call using a GString:
また、GStringを使用した以下のような呼び出しも同様です:

def vulnerable() {
    def books = Book.find("from Book as b where b.title ='${params.title}'")
}

Do not do this. Use named or positional parameters instead to pass in parameters:
パラメータをそのまま渡すのではなく、必ず位置パラメータまたは名前付きパラメータを使うようにしましょう:

def safe() {
    def books = Book.find("from Book as b where b.title = ?",
                          [params.title])
}

or
または、次のように書くこともできます:

def safe() {
    def books = Book.find("from Book as b where b.title = :title",
                          [title: params.title])
}

h4. Phishing

フィッシング

This really a public relations issue in terms of avoiding hijacking of your branding and a declared communication policy with your customers. Customers need to know how to identify valid emails.
あなたとお客様との間で交わされたコミュニケーションポリシーのもと、あなたのブランドのハイジャックを防ぐという観点から、これはまさしく広報の問題です。顧客には、(不正な発信元でない)真正なEメールであることをどう見分けるか、知らせておく必要があります。

h4. XSS - cross-site scripting injection

XSS - クロスサイトスクリプティングインジェクション

It is important that your application verifies as much as possible that incoming requests were originated from your application and not from another site. It is also important to ensure that all data values rendered into views are escaped correctly. For example when rendering to HTML or XHTML you must ensure that people cannot maliciously inject JavaScript or other HTML into data or tags viewed by others.
要求されたリクエストがあなたのアプリケーションのものであり、他のサイトからではないということを、できる限り検証することが重要です。ビューにレンダリングされる全てのデータが、確実に、正しくエスケープ処理されることもまた重要です。例えば、HTMLまたはXHTMLをレンダリングする際、他人が見ることができるデータやタグに対して、JavaScriptや他のHTMLを悪意を持って挿入することができないようにする必要があります。

Grails 2.3 and above include special support for automatically encoded data placed into GSP pages. See the documentation on Cross Site Scripting (XSS) prevention for further information.
Grails 2.3以降では、自動的にエンコードしたデータをGSPに配置する仕組みが実装されています。詳しくは クロスサイトスクリプティング(XSS)防御 のドキュメントを参照してください。

You must also avoid the use of request parameters or data fields for determining the next URL to redirect the user to. If you use a successURL parameter for example to determine where to redirect a user to after a successful login, attackers can imitate your login procedure using your own site, and then redirect the user back to their own site once logged in, potentially allowing JavaScript code to then exploit the logged-in account on the site.
ユーザのリダイレクト先URLを決めるためにリクエストパラメータやデータフィールドを使うこともまた、避けなければなりません。ログイン成功後、ユーザをどこへリダイレクトするか決定するために、例えば、あなたがsuccessURLパラメータを使うような場合、攻撃者は、あなた自身のサイトを利用してログイン手順を偽装し、ユーザがログインしようとしたときに攻撃者自身のサイトにリダイレクトさせることができてしまいます。これは、潜在的に、サイト上のログインアカウントを悪用するJavaScriptコードを許していることになります。

h4. Cross-site request forgery

クロスサイトリクエストフォージェリ

CSRF involves unauthorized commands being transmitted from a user that a website trusts. A typical example would be another website embedding a link to perform an action on your website if the user is still authenticated.
CSRFは、ウェブサイト上の正規ユーザから、承認されていないコマンド送信を引き起こします。認証されている状態のユーザが、別のウェブサイト内に埋め込まれたリンクによって、あなたのウェブサイト上で意図しないアクションを引き起こすようなものが典型的な例です。

The best way to decrease risk against these types of attacks is to use the useToken attribute on your forms. See Handling Duplicate Form Submissions for more information on how to use it. An additional measure would be to not use remember-me cookies.
こうした攻撃のリスクを軽減する最良の方法は、フォームにuseToken属性を使うことです。使い方についての詳細は、フォーム二重送信のハンドリングを参照してください。加えて、「次回からパスワードの入力を省略する」というような機能を提供するクッキーを使わないことも対策の一つです。

h4. HTML/URL injection

HTML/URLインジェクション

This is where bad data is supplied such that when it is later used to create a link in a page, clicking it will not cause the expected behaviour, and may redirect to another site or alter request parameters.
これは、悪意のあるデータが与えられ、後にあるページにおいてリンクの生成に使用されると、クリックしても期待するような動作にならない事象を指します。そして、別のサイトにリダイレクトされたり、要求パラメータを改ざんされたりする可能性もあります。

HTML/URL injection is easily handled with the codecs supplied by Grails, and the tag libraries supplied by Grails all use encodeAsURL where appropriate. If you create your own tags that generate URLs you will need to be mindful of doing this too.
HTML/URLインジェクションは、Grailsが提供するコーデックにより、容易に対処できます。また、Grailsが提供しているタグライブラリは、全て適切なところでencodeAsURLを使います。もし、URLを生成するようなタグを自分で作成するのなら、この対処も意識しておく必要があるでしょう。

h4. Denial of service

サービス妨害

Load balancers and other appliances are more likely to be useful here, but there are also issues relating to excessive queries for example where a link is created by an attacker to set the maximum value of a result set so that a query could exceed the memory limits of the server or slow the system down. The solution here is to always sanitize request parameters before passing them to dynamic finders or other GORM query methods:
ここでは、負荷分散装置やその他のアプライアンスが、より有用でしょう。ですが、サーバのメモリ容量を超えること、あるいはシステムを遅くさせることを目的に、結果の最大値を書き換えた超過クエリを発行するようなリンクを攻撃者が作成する、といった課題もあります。これに対する解決法は、ダイナミックファインダーやその他のGORMクエリメソッドにリクエストパラメータを渡す前に、常にサニタイズすることです:

def safeMax = Math.max(params.max?.toInteger(), 100) // limit to 100 results
return Book.list(max:safeMax)
def safeMax = Math.max(params.max?.toInteger(), 100) // 結果を100件に制限する
return Book.list(max:safeMax)

h4. Guessable IDs

推測可能なID

Many applications use the last part of the URL as an "id" of some object to retrieve from GORM or elsewhere. Especially in the case of GORM these are easily guessable as they are typically sequential integers.
多くのアプリケーションで、URLの最後の部分を、GORMや他のところから取り出す何らかのオブジェクトのIDとして利用するでしょう。特にGORMの場合、これらは容易に推測可能です。なぜならそれは、一般的にシーケンシャルな整数だからです。

Therefore you must assert that the requesting user is allowed to view the object with the requested id before returning the response to the user.
それゆえ、ユーザにレスポンスを返す前に、要求しているユーザが、要求されているIDのオブジェクトを見ることができるか必ず検証するべきです。

Not doing this is "security through obscurity" which is inevitably breached, just like having a default password of "letmein" and so on.
これをしないということは "security through obscurity(※脆弱性をユーザーから隠せば、悪用は防げるという考え)" であり、すなわち "letmein" のようなデフォルトパスワードを使うのと同様、そのうち破られることになるでしょう。

You must assume that every unprotected URL is publicly accessible one way or another.
いずれにせよ、全ての保護されていないURLは、当然誰からもアクセス可能であると考えなければなりません。

14.2 クロスサイトスクリプティング(XSS)防御

Cross Site Scripting (XSS) attacks are a common attack vector for web applications. They typically involve submitting HTML or Javascript code in a form such that when that code is displayed, the browser does something nasty. It could be as simple as popping up an alert box, or it could be much worse. The solution is to escape all untrusted user input when it is displayed in a page. For example,

<script>alert('Got ya!');</script>

will become

&lt;script&gt;alert('Got ya!');&lt;/script&gt;

when rendered, nullifying the effects of the malicious input.

By default, Grails plays it safe and escapes all content in ${} expressions in GSPs. All the standard GSP tags are also safe by default, escaping any relevant attribute values.

So what happens when you want to stop Grails from escaping some content? There are valid use cases for putting HTML into the database and rendering it as-is, as long as that content is trusted. In such cases, you can tell Grails that the content is safe as should be rendered raw, i.e. without any escaping:

<section>${raw(page.content)}</section>

The raw() method you see here is available from controllers, tag libraries and GSP pages.

Although Grails plays it safe by default, that is no guarantee that your application will be invulnerable to an XSS-style attack. Such an attack is less likely to succeed than would otherwise be the case, but developers should always be conscious of potential attack vectors and attempt to uncover vulnerabilities in the application during testing. It's also easy to switch to an unsafe default, thereby increasing the risk of a vulnerability being introduced.

It's difficult to make a solution that works for everyone, and so Grails provides a lot of flexibility with regard to fine-tuning how escaping works, allowing you to keep most of your application safe while switching off default escaping or changing the codec used for pages, tags, page fragments, and more.

Configuration

It is recommended that you review the configuration of a newly created Grails application to garner an understanding of XSS prevention works in Grails.

GSP features the ability to automatically HTML encode GSP expressions, and as of Grails 2.3 this is the default configuration. The default configuration (found in Config.groovy) for a newly created Grails application can be seen below:

grails {
        views {
            gsp {
                encoding = 'UTF-8'
                htmlcodec = 'xml' // use xml escaping instead of HTML4 escaping
                codecs {
                    expression = 'html' // escapes values inside ${}
                    scriptlet = 'html' // escapes output from scriptlets in GSPs
                    taglib = 'none' // escapes output from taglibs
                    staticparts = 'none' // escapes output from static template parts
                }
            }
            // escapes all not-encoded output at final stage of outputting
            filteringCodecForContentType {
                //'text/html' = 'html'
            }
        }
    }

GSP features several codecs that it uses when writing the page to the response. The codecs are configured in the codecs block and are described below:

  • expression - The expression codec is used to encode any code found within ${..} expressions. The default for newly created application is html encoding.
  • scriptlet - Used for output from GSP scriplets (<% %>, <%= %> blocks). The default for newly created applications is html encoding
  • taglib - Used to encode output from GSP tag libraries. The default is none for new applications, as typically it is the responsibility of the tag author to define the encoding of a given tag and by specifying none Grails remains backwards compatible with older tag libraries.
  • staticparts - Used to encode the raw markup output by a GSP page. The default is none.

Double Encoding Prevention

Versions of Grails prior to 2.3, included the ability to set the default codec to html, however enabling this setting sometimes proved problematic when using existing plugins due to encoding being applied twice (once by the html codec and then again if the plugin manually called encodeAsHTML).

Grails 2.3 includes double encoding prevention so that when an expression is evaluated, it will not encode if the data has already been encoded (Example ${foo.encodeAsHTML()}).

Raw Output

If you are 100% sure that the value you wish to present on the page has not been received from user input, and you do not wish the value to be encoded then you can use the raw method:

${raw(book.title)}

The 'raw' method is available in tag libraries, controllers and GSP pages.

Per Plugin Encoding

Grails also features the ability to control the codecs used on a per plugin basis. For example if you have a plugin named foo installed, then placing the following configuration in your application's Config.groovy will disable encoding for only the foo plugin

foo.grails.views.gsp.codecs.expression = "none"

Per Page Encoding

You can also control the various codecs used to render a GSP page on a per page basis, using a page directive:

<%@page expressionCodec="none" %>

Per Tag Library Encoding

Each tag library created has the opportunity to specify a default codec used to encode output from the tag library using the "defaultEncodeAs" property:

static defaultEncodeAs = 'html'

Encoding can also be specified on a per tag basis using "encodeAsForTags":

static encodeAsForTags = [tagName: 'raw']

Context Sensitive Encoding Switching

Certain tags require certain encodings and Grails features the ability to enable a codec only a certain part of a tag's execution using the "withCodec" method. Consider for example the "<g:javascript>"" tag which allows you to embed JavaScript code in the page. This tag requires JavaScript encoding, not HTML coding for the execution of the body of the tag (but not for the markup that is output):

out.println '<script type="text/javascript">'
    withCodec("JavaScript") {
        out << body()
    }
    out.println()
    out.println '</script>'

Forced Encoding for Tags

If a tag specifies a default encoding that differs from your requirements you can force the encoding for any tag by passing the optional 'encodeAs' attribute:

<g:message code="foo.bar" encodeAs="JavaScript" />

Default Encoding for All Output

The default configuration for new applications is fine for most use cases, and backwards compatible with existing plugins and tag libraries. However, you can also make your application even more secure by configuring Grails to always encode all output at the end of a response. This is done using the filteringCodecForContentType configuration in Config.groovy:

grails.views.gsp.filteringCodecForContentType.'text/html' = 'html'

Note that, if activated, the staticparts codec typically needs to be set to raw so that static markup is not encoded:

codecs {
        expression = 'html' // escapes values inside ${}
        scriptlet = 'html' // escapes output from scriptlets in GSPs
        taglib = 'none' // escapes output from taglibs
        staticparts = 'raw' // escapes output from static template parts
    }

14.3 エンコード・デコードオブジェクト

Grails supports the concept of dynamic encode/decode methods. A set of standard codecs are bundled with Grails. Grails also supports a simple mechanism for developers to contribute their own codecs that will be recognized at runtime.
Grailsは動的なエンコード/デコードメソッドという考え方をサポートしています。標準的なコーデックはGrailsにバンドルされているほか、開発者が独自のコーデックを簡単に定義することのできるメカニズムも備えています。

h4. Codec Classes

コーデッククラス

A Grails codec class is one that may contain an encode closure, a decode closure or both. When a Grails application starts up the Grails framework dynamically loads codecs from the grails-app/utils/ directory.
Grailsのコーデッククラスは、encodeクロージャとdecodeクロージャのいずれか、または両方を実装したものです。Grailsフレームワークは、Grailsアプリケーションが起動するときに、grails-app/utils/ディレクトリ以下にあるコーデックを動的にロードします。

The framework looks under grails-app/utils/ for class names that end with the convention Codec. For example one of the standard codecs that ships with Grails is HTMLCodec.
Grailsフレームワークはgrails-app/utils/ディレクトリ以下にある、Codecという名前で終わるクラスを探します。例えば、Grailsに標準で実装されているコーデックの一つにHTMLCodecがあります。

If a codec contains an encode closure Grails will create a dynamic encode method and add that method to the Object class with a name representing the codec that defined the encode closure. For example, the HTMLCodec class defines an encode closure, so Grails attaches it with the name encodeAsHTML.
コーデックにencodeクロージャが定義されている場合、Grailsは動的なencodeメソッドを作成し、そのクロージャを定義しているコーデックの名前でそのメソッドをObjectクラスに追加します。例えば、HTMLCodecクラスではencodeクロージャが定義されているため、GrailsはencodeAsHTMLという名前でメソッドを追加します。

The HTMLCodec and URLCodec classes also define a decode closure, so Grails attaches those with the names decodeHTML and decodeURL respectively. Dynamic codec methods may be invoked from anywhere in a Grails application. For example, consider a case where a report contains a property called 'description' which may contain special characters that must be escaped to be presented in an HTML document. One way to deal with that in a GSP is to encode the description property using the dynamic encode method as shown below:
さらに、HTMLCodecクラスとURLCodecクラスではdecodeクロージャも定義されているので、GrailsはこれらをそれぞれdecodeHTML, decodeURLという名前で追加します。動的なコーデックメソッドはGrailsアプリケーションのどこからでも呼び出すことができます。例えば、reportdescriptionという名前のプロパティを持っているケースを想定します。descriptionは特殊文字を文字を含んでいる可能性があるため、HTMLドキュメントとして表示させる前にエスケープする必要があるとします。GSPでこれを実現する一つの方法は、以下のように、動的なエンコードメソッドを使用してdescriptionプロパティをエンコードすることです:

${report.description.encodeAsHTML()}

Decoding is performed using value.decodeHTML() syntax.
同様に、デコードはvalue.decodeHTML()というような形で行うことができます。

h4. Standard Codecs

標準コーデック

HTMLCodec
HTMLCodec

This codec performs HTML escaping and unescaping, so that values can be rendered safely in an HTML page without creating any HTML tags or damaging the page layout. For example, given a value "Don't you know that 2 > 1?" you wouldn't be able to show this safely within an HTML page because the > will look like it closes a tag, which is especially bad if you render this data within an attribute, such as the value attribute of an input field.
このコーデックはHTMLのエスケープ/アンエスケープ処理を行います。これにより、HTMLタグが挿入されたりレイアウトを破壊される恐れなく、安全にHTMLページで値を表示することができます。例えば、"Don't you know that 2 > 1?" という文章を表示することを考えてみます。> が閉じタグのように扱われてしまうため、この値をエスケープ処理なしで安全にHTMLページに表示させることはできません。このようなデータを属性 (例えばinputフィールドのvalue属性) の中に表示させる場合はさらに大変です。

Example of usage:
使用例を以下に示します:

<input name="comment.message" value="${comment.message.encodeAsHTML()}"/>

Note that the HTML encoding does not re-encode apostrophe/single quote so you must use double quotes on attribute values to avoid text with apostrophes affecting your page.
HTMLエンコードでは、アポストロフィ/シングルクォートを再エンコードしないことに注意してください。エンコードする文字列にアポストロフィが入っている場合に備えて、属性の値はダブルクォートで括ってください。

URLCodec
URLCodec

URL encoding is required when creating URLs in links or form actions, or any time data is used to create a URL. It prevents illegal characters from getting into the URL and changing its meaning, for example "Apple & Blackberry" is not going to work well as a parameter in a GET request as the ampersand will break parameter parsing.
URLエンコードは、リンクやフォームのアクション用にURLを生成する場合や、データを使ってURLを作成するあらゆる場合に必要です。エンコードすることによって、URLに不正な文字列が混入して意味を変えてしまうことを防ぐことができます。例えば、"Apple & Blackberry" という文字列には & 記号が含まれているため、そのままGETリクエストのパラメタとして使用することができません。

Example of usage:
使用例を以下に示します:

<a href="/mycontroller/find?searchKey=${lastSearch.encodeAsURL()}">
Repeat last search
</a>

Base64Codec
Base64Codec

Performs Base64 encode/decode functions. Example of usage:
Base64エンコード/デコードを行います。使用例を以下に示します:

Your registration code is: ${user.registrationCode.encodeAsBase64()}

JavaScriptCodec
JavaScriptCodec

Escapes Strings so they can be used as valid JavaScript strings. For example:
JavaScriptの文字列として正しい形式になるように、文字列をエスケープします。例えば次のように使用します:

Element.update('${elementId}',
    '${render(template: "/common/message").encodeAsJavaScript()}')

HexCodec
HexCodec

Encodes byte arrays or lists of integers to lowercase hexadecimal strings, and can decode hexadecimal strings into byte arrays. For example:
byte配列または整数のリストを小文字16進数表記の文字列にエンコードしたり、逆に16進数表記の文字列をbyte配列にデコードすることができます。例えば次のように使用します:

Selected colour: #${[255,127,255].encodeAsHex()}

MD5Codec
MD5Codec

Uses the MD5 algorithm to digest byte arrays or lists of integers, or the bytes of a string (in default system encoding), as a lowercase hexadecimal string. Example of usage:
MD5アルゴリズムを使用してbyte配列や整数のリスト、文字列 (システムのデフォルトエンコーディング) のダイジェスト値を計算し、小文字16進数表記の文字列にエンコードします。使用例を以下に示します:

Your API Key: ${user.uniqueID.encodeAsMD5()}

MD5BytesCodec
MD5BytesCodec

Uses the MD5 algorithm to digest byte arrays or lists of integers, or the bytes of a string (in default system encoding), as a byte array. Example of usage:
MD5アルゴリズムを使用してbyte配列や整数のリスト、文字列 (システムのデフォルトエンコーディング) のダイジェスト値を計算し、byte配列にエンコードします。使用例を以下に示します:

byte[] passwordHash = params.password.encodeAsMD5Bytes()

SHA1Codec
SHA1Codec

Uses the SHA1 algorithm to digest byte arrays or lists of integers, or the bytes of a string (in default system encoding), as a lowercase hexadecimal string. Example of usage:
SHA1アルゴリズムを使用してbyte配列や整数のリスト、文字列 (システムのデフォルトエンコーディング) のダイジェスト値を計算し、小文字16進数表記の文字列にエンコードします。使用例を以下に示します:

Your API Key: ${user.uniqueID.encodeAsSHA1()}

SHA1BytesCodec
SHA1BytesCodec

Uses the SHA1 algorithm to digest byte arrays or lists of integers, or the bytes of a string (in default system encoding), as a byte array. Example of usage:
SHA1アルゴリズムを使用してbyte配列や整数のリスト、文字列 (システムのデフォルトエンコーディング) のダイジェスト値を計算し、byte配列にエンコードします。使用例を以下に示します:

byte[] passwordHash = params.password.encodeAsSHA1Bytes()

SHA256Codec
SHA256Codec

Uses the SHA256 algorithm to digest byte arrays or lists of integers, or the bytes of a string (in default system encoding), as a lowercase hexadecimal string. Example of usage:
SHA256アルゴリズムを使用してbyte配列や整数のリスト、文字列 (システムのデフォルトエンコーディング) のダイジェスト値を計算し、小文字16進数表記の文字列にエンコードします。使用例を以下に示します:

Your API Key: ${user.uniqueID.encodeAsSHA256()}

SHA256BytesCodec
SHA256BytesCodec

Uses the SHA256 algorithm to digest byte arrays or lists of integers, or the bytes of a string (in default system encoding), as a byte array. Example of usage:
SHA256アルゴリズムを使用してbyte配列や整数のリスト、文字列 (システムのデフォルトエンコーディング) のダイジェスト値を計算し、byte配列にエンコードします。使用例を以下に示します:

byte[] passwordHash = params.password.encodeAsSHA256Bytes()

h4. Custom Codecs

カスタムコーデック

Applications may define their own codecs and Grails will load them along with the standard codecs. A custom codec class must be defined in the grails-app/utils/ directory and the class name must end with Codec. The codec may contain a static encode closure, a static decode closure or both. The closure must accept a single argument which will be the object that the dynamic method was invoked on. For Example:
アプリケーションで必要なコーデックを定義しておくと、Grailsは標準コーデックと同様にロードします。カスタムコーデックのクラスはgrails-app/utils/ディレクトリ以下に配置され、かつ、クラス名はCodecで終わる必要があります。コーデックにはstatic encodeクロージャとstatic decodeクロージャのいずれかまたは両方を定義することができます。これらのクロージャは、1引数 (動的なメソッドとして実行された際にエンコード/デコード対象のオブジェクトになります) を受け付ける必要があります。例えば、以下のように記述します:

class PigLatinCodec {
  static encode = { str ->
    // convert the string to pig latin and return the result
  }
}

With the above codec in place an application could do something like this:
上の例のようなコーデックが定義されているとき、アプリケーションから以下のように使用することができます:

${lastName.encodeAsPigLatin()}

14.4 認証

Grails has no default mechanism for authentication as it is possible to implement authentication in many different ways. It is however, easy to implement a simple authentication mechanism using either interceptors or filters. This is sufficient for simple use cases but it's highly preferable to use an established security framework, for example by using the Spring Security or the Shiro plugin.
認証は様々な方法で実装することができるため、Grailsではデフォルトの認証メカニズムを提供していません。インターセプターフィルタを使用することで、単純な認証であれば簡単に実装することができます。これらの機能は多くのユースケースにおいて十分ですが、実績のあるセキュリティフレームワークを使用することがより望ましいでしょう。セキュリティフレームワークには、例えばSpring SecurityShiroプラグインなどがあります。

Filters let you apply authentication across all controllers or across a URI space. For example you can create a new set of filters in a class called grails-app/conf/SecurityFilters.groovy by running:
フィルタを使うと、すべてのコントローラやURI空間に対して認証を適用できます。例えば、以下のコマンドを実行することで、grails-app/conf/SecurityFilters.groovyというクラスに新しいフィルタセットが生成されます:

grails create-filters security

and implement your interception logic there:
このクラスに、インターセプターのロジックを実装します:

class SecurityFilters {
    def filters = {
        loginCheck(controller: '*', action: '*') {
            before = {
                if (!session.user && actionName != "login") {
                    redirect(controller: "user", action: "login")
                    return false
                }
            }
        }
    }
}

Here the loginCheck filter intercepts execution before all actions except login are executed, and if there is no user in the session then redirect to the login action.
この例では、loginCheckフィルタがすべてのアクションの実行前にインターセプトされます。ただし、セッションにユーザが存在しない状態でlogin以外のアクションが呼び出された場合は、loginアクションにリダイレクトされます。

The login action itself is simple too:
loginアクションの実装も簡単です:

def login() {
    if (request.get) {
        return // render the login view
    }

def u = User.findByLogin(params.login) if (u) { if (u.password == params.password) { session.user = u redirect(action: "home") } else { render(view: "login", model: [message: "Password incorrect"]) } } else { render(view: "login", model: [message: "User not found"]) } }

14.5 セキュリティプラグイン

If you need more advanced functionality beyond simple authentication such as authorization, roles etc. then you should consider using one of the available security plugins.
認可やロールなど、単純な認証以上の機能が必要な場合、以下のようなセキュリティプラグインの利用を検討してください。

14.5.1 Spring Security

The Spring Security plugins are built on the Spring Security project which provides a flexible, extensible framework for building all sorts of authentication and authorization schemes. The plugins are modular so you can install just the functionality that you need for your application. The Spring Security plugins are the official security plugins for Grails and are actively maintained and supported.
Spring Securityプラグインは、Spring SecurityプロジェクトをGrailsで利用可能にします。Spring Securityプロジェクトでは、様々な種類の認証/認可スキームを実装するための柔軟で拡張可能なフレームワークを提供しています。このプラグインはモジュール化されているため、アプリケーションに必要な機能だけをインストールすることができます。Spring SecurityプラグインはGrailsの公式セキュリティプラグインで、活発にメンテナンスとサポートが行われています。

There is a Core plugin which supports form-based authentication, encrypted/salted passwords, HTTP Basic authentication, etc. and secondary dependent plugins provide alternate functionality such as OpenID authentication, ACL support, single sign-on with Jasig CAS, LDAP authentication, Kerberos authentication, and a plugin providing user interface extensions and security workflows.
Coreプラグインでは、フォームベースの認証、パスワードの暗号化(ソルトを加えることもできる)、HTTP Basic認証などをサポートしています。Coreプラグインに依存するプラグインを利用することで、例えばOpenID認証ACLJasig CASを利用したシングルサインオンLDAP認証Kerberos認証などの機能を利用できるほか、ユーザインタフェース拡張やセキュリティワークフローを提供するプラグインもあります。

See the Core plugin page for basic information and the user guide for detailed information.
基本的な情報についてはCoreプラグインのページを、詳細な情報についてはユーザガイドをご覧ください。

14.5.2 Shiro

Shiro is a Java POJO-oriented security framework that provides a default domain model that models realms, users, roles and permissions. With Shiro you extend a controller base class called JsecAuthBase in each controller you want secured and then provide an accessControl block to setup the roles. An example below:
ShiroはJava POJO指向のセキュリティフレームワークで、レルム/ユーザ/ロール/権限に対するデフォルトのドメインモデルを提供します。Shiroを利用するには、セキュリティ機能が必要な各コントローラでJsecAuthBaseという基底クラスを継承し、accessControlブロックを使用してロールを設定します。以下に例を示します:

class ExampleController extends JsecAuthBase {
    static accessControl = {
        // All actions require the 'Observer' role.
        role(name: 'Observer')

// The 'edit' action requires the 'Administrator' role. role(name: 'Administrator', action: 'edit')

// Alternatively, several actions can be specified. role(name: 'Administrator', only: [ 'create', 'edit', 'save', 'update' ]) } … }

For more information on the Shiro plugin refer to the documentation.
Shiroプラグインについてのより詳しい情報は、ドキュメントを参照してください。