Amankan aplikasi Web, gaya Java

Keamanan web dapat ditentukan dengan berbagai cara, tergantung pada sudut pandang individu. Fokus utama keamanan dalam artikel ini adalah keamanan aplikasi yang dikembangkan dan digunakan untuk Internet. Di sini, saya akan menjelaskan beberapa tindakan keamanan perangkat lunak yang dapat Anda lakukan untuk mengamankan aplikasi Anda. Meskipun tidak ada yang benar-benar sempurna, menggabungkan pendekatan ini dengan perangkat keras dapat membantu mencegah serangan jahat pada bisnis Anda.

Dua konsep utama keamanan adalah otentikasi dan otorisasi. Saya akan menjelaskan masing-masing di bagian berikut dan memberikan contoh bagaimana Anda dapat menerapkannya dalam aplikasi Anda. Selain itu, saya akan membahas beberapa kelas kunci dari Java Security API untuk mempersiapkan contoh yang lebih rinci yang menggabungkan otentikasi berbasis formulir dengan model keamanan Java. Konsep yang diuraikan dalam contoh harus memungkinkan perusahaan Anda menghasilkan kebijakan keamanan untuk aplikasi berbasis Java Anda.

Autentikasi

Otentikasi adalah proses di mana hak akses pengguna diverifikasi sebelum mereka memasuki kawasan lindung Situs Web. Ada dua pendekatan otentikasi utama: otentikasi dasar dan otentikasi berbasis formulir.

Otentikasi dasar

Otentikasi dasar bergantung pada server Web untuk otentikasi ke area yang dilindungi. Situs yang dilindungi oleh otentikasi dasar memungkinkan pengguna menelusuri area yang tidak dilindungi tanpa mengharuskan pengguna memasukkan kata sandi. Namun, browser secara otomatis akan meminta kata sandi dan nama pengguna kepada pengguna jika dia mencoba mengakses halaman aman. Prompt ini muncul dalam bentuk kotak dialog.

Kombinasi nama pengguna dan kata sandi kemudian dikodekan (basis 64) dan diteruskan dalam bentuk tidak terenkripsi ke server Web. Server Web membandingkan nilai yang dikodekan dengan nilai yang disimpan dalam file datar, database, atau server direktori.

Jika pengguna diotentikasi, server kemudian memverifikasi bahwa pengguna memiliki hak istimewa untuk mengakses halaman yang diminta terhadap file, seperti httpd.conf. Jika pengguna memiliki akses, server Web kemudian menyajikan halaman tersebut. Jika pengguna ditolak aksesnya, server akan meminta kombinasi nama pengguna / sandi lagi atau menampilkan pesan kesalahan di jendela browser.

Karena sintaks sebenarnya dari otentikasi dasar bervariasi antar server, saya tidak menyajikannya di sini. Ada banyak sumber daya Web yang menjelaskan sintaks dari berbagai server.

Otentikasi berbasis formulir

Sebagian besar situs menggunakan pendekatan yang disebut autentikasi malas berbasis formulir, yang memungkinkan pengguna menavigasi melalui area situs yang tidak dilindungi tanpa memerlukan sandi. Hanya ketika pengguna ingin mengakses kawasan lindung, seperti pemesanan atau status akun, apakah situs tersebut menampilkan formulir login. Ini adalah pendekatan keamanan yang paling umum dan digunakan oleh perusahaan e-commerce besar, seperti Barnes & Noble. Manfaat dari pendekatan ini adalah bahwa pengguna tidak dikenakan waktu tunggu yang terkait dengan otentikasi kecuali mereka benar-benar membutuhkan akses ke halaman yang dilindungi.

Sebagai skema keamanan paling umum di Web, autentikasi malas berbasis formulir cocok dengan contoh yang disajikan di artikel ini.

Gunakan formulir untuk mengotentikasi klien

Cara umum untuk sistem berbasis servlet untuk melakukan otentikasi adalah dengan menggunakan sesi untuk menyimpan informasi yang menunjukkan bahwa pengguna telah masuk ke sistem. Dalam skema ini, logika otentikasi menggunakan HttpSessionobjek yang dikelola oleh mesin servlet di server Web.

Sebuah servlet dasar dengan pengetahuan otentikasi sangat membantu dalam kasus ini. Dengan menggunakan servicemetode BaseServlet, servlet yang diperluas dapat menggunakan kembali fungsionalitas pemeriksaan keamanan. Semua kode yang digunakan dalam contoh ini dapat ditemukan di Resources.

The serviceMetode ditampilkan dalam potongan kode berikut:

public void service (permintaan HttpServletRequest, tanggapan HttpServletResponse) melempar IOException, ServletException {// periksa untuk melihat apakah sesi telah dibuat untuk pengguna ini // jangan buat sesi baru dulu. Sesi HttpSession = request.getSession (false); String dimintaPage = request.getParameter (Constants.REQUEST); if (session! = null) {// ambil parameter otentikasi dari sesi Boolean isAuthenticated = (Boolean) session.getValue (Constants.AUTHENTICATION); // jika pengguna tidak diautentikasi if (! isAuthenticated.booleanValue ()) {// proses permintaan unauthenticated unauthenticatedUser (response, requestPage); }} else // sesi tidak ada {// oleh karena itu pengguna tidak diotentikasi // proses permintaan tidak terauthentikasi unauthenticatedUser (response, requestPage); }}

Perhatikan bahwa Anda dapat memperluas metode ini untuk melakukan fungsi umum lainnya juga. Dalam contoh ini, saya hanya mengembangkan aspek keamanan kelas ini.

The BaseServletupaya untuk mengambil sesi dari mesin servlet. Saat pengambilan, servlet memverifikasi bahwa pengguna telah diberikan akses ke sistem. Jika salah satu dari pemeriksaan ini gagal, servlet mengarahkan browser ke layar login.

Pada layar login, pengguna diminta memasukkan nama pengguna dan kata sandi. Perhatikan bahwa data yang dikirimkan dari browser ke server Web tidak dienkripsi kecuali Anda menggunakan Secure Socket Layer (SSL).

The LoginServletmenggunakan kombinasi username / password untuk query database untuk memastikan bahwa pengguna ini memang memiliki akses ke sistem. Jika pemeriksaan gagal mengembalikan catatan untuk pengguna itu, layar login ditampilkan kembali. Jika pemeriksaan berhasil, kode berikut menyimpan informasi otentikasi pengguna di dalam variabel sesi.

// buat sesi sesi = request.getSession (true); // konversikan boolean menjadi Boolean Boolean booleanIsAuthenticated = new Boolean (isAuthenticated); // simpan nilai boolean ke sesi session.putValue (Constants.AUTHENTICATION, booleanIsAuthenticated);

Dalam contoh ini, diasumsikan bahwa setiap pengguna yang berhasil mengautentikasi ke sistem memiliki akses ke halaman yang ditampilkan sebelum login. Namun, ada kasus di mana tim pengembangan aplikasi mungkin memerlukan pendekatan keamanan yang lebih baik untuk memenuhi persyaratannya.

Otorisasi

Otorisasi memverifikasi bahwa kebijakan keamanan melindungi dari peretas yang lebih canggih dengan mencegah kode yang tidak sah terhubung ke sistem back-office, seperti Enterprise JavaBeans (EJB). Ada dua jenis otorisasi: otorisasi kode dan otorisasi penelepon.

Otorisasi kode

Tim keamanan Anda dapat mencegah penggunaan kode yang tidak sah dengan membatasi kelas yang tersedia untuk mesin virtual yang digunakan oleh mesin servlet. Anda dapat mencapai proses otorisasi kode ini dengan menghapus entri yang tidak diperlukan dari classpath.

Tim keamanan memiliki kendali penuh atas kode mana yang harus dimasukkan dalam classpath dan oleh karena itu dapat mengotorisasi kode sebelum dimasukkan. Tim harus memastikan bahwa kode tersebut tidak memiliki akses ke alat pihak ketiga atau kode asing.

Otorisasi penelepon

Selain otorisasi kode, Anda juga dapat mengotentikasi penelepon dari sistem back-office. Model EJB, misalnya, memungkinkan tim pengembangan menentukan nama pengguna dan kata sandi untuk akses ke kacang apa pun yang disebarkan dalam wadah.

Kode apa pun yang mencoba untuk terhubung ke kacang ini harus meneruskan kombinasi nama pengguna / kata sandi ke wadah untuk otorisasi. Otorisasi yang gagal menghasilkan pengecualian yang mencegah penelepon menyelesaikan tindakannya.

Contoh otorisasi

In this second example, I'll explore the mechanisms built into the EJB specification for preventing unauthorized access to the business logic. While this example is based on the WebLogic Tengah server, the concepts hold true for other servers even though the syntax will differ. See Resources for the code or configuration files used in this example.

In the EJB's deployment descriptor, the following code identifies the access control entries associated with the bean:

(accessControlEntries DEFAULT [administrators basicUsers] theRestrictedMethod [administrators] ); end accessControlEntries 

Notice that two user categories have been identified. Administrators have access to the bean by default and constitute the only user group that has access to theRestrictedMethod.

Once you've authorized that the administrators have access to the bean, you now need to create properties detailing which users are in the administrators group. To do this, the weblogic.properties file must include the following lines:

weblogic.password.JoeAdministrator=joe weblogic.security.group.administrators=JoeAdministrator weblogic.password.JaneBasic=jane weblogic.security.group.basicUsers=JaneBasic 

At this point, you've established the users who have access to the bean and have restricted certain specific methods. This helps limit the potential for malicious attacks on your Web server to reach the business logic stored in the beans.

The last step in this EJB authorization example is to establish the client connection to the bean. In this case, the client must specify the username/password combination properly in order to have access to the restricted bean or methods. An example client communication follows:

try{ Properties myProperties = new Properties(); myProperties.put( Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.T3InitialContextFactory"); myProperties.put(Context.PROVIDER_URL, "t3://localhost:7001"); myProperties.put(Context.SECURITY_PRINCIPAL, "JoeAdministrator"); myProperties .put(Context.SECURITY_CREDENTIALS, "joe"); ic = new InitialContext(myProperties); ... } catch (Exception e) { ... } 

Since you've passed the JoeAdministrator user to the InitialContext, you'll have access to any method to which the administrators group has been granted access. If your application makes connections to external beans or your beans are used by external applications, you should implement this security authorization.

Java security

In the Java Security API, there is a package, java.security.acl, that contains several classes that you can use to establish a security system in Java. These classes enable your development team to specify different access capabilities for users and user groups. All code used in this example can be found in Resources.

The concept is fairly straightforward. A user or user group is granted permission to functionality by adding that user or group to an access control list. For example, consider a java.security.Principal called testUser as shown below:

Principal testUser = new PrincipalImpl ("testUser"); 

Now you can create a Permission object to represent the capability of reading from a file.

Permission fileRead = new PermissionImpl ("readFile"); 

Once you have created the user and the user's permission, you can create the access control list entry. It's important to note that the security APIs require that the owner of the access list be passed in order to ensure that this is truly the developer's desired action. It is essential that this owner object be protected carefully.

Acl accessList = AclImpl baru (pemilik, "exampleAcl"); 

Dalam bentuk akhirnya, daftar akses akan berisi sekumpulan entri daftar akses. Anda dapat membuatnya sebagai berikut:

AclEntry aclEntry = AclEntryImpl baru (testUser); aclEntry.addPermission (fileRead); accessList.addEntry (pemilik, aclEntry);

Baris sebelumnya membuat AclEntryobjek baru untuk testUser, menambahkan fileReadizin ke entri tersebut, dan lalu menambahkan entri ke daftar kontrol akses.

Sekarang Anda dapat memeriksa izin pengguna dengan cukup mudah, sebagai berikut:

boolean isReadFileAuthorized = accessList.checkPermission (testUser, readFile);