Http Authentication Java
http://docs.oracle.com/javase/7/docs/technotes/guides/net/http-auth.html
Http Authentication
Overview
The HTTP protocol handler implements a number of authentication schemes. Sun's implementation of Java SE Version 6 supports the following:
- HTTP Basic authentication (RFC2617)
- HTTP Digest authentication (RFC2617)
- NTLM (defined by Microsoft)
- Http SPNEGO Negotiate (defined by Microsoft), with the following underlying mechanisms:
- Kerberos
- NTLM
Each of these schemes is described in more detail below, but they are typically used by application code in much the same way. The java.net.Authenticator class is used to enable authentication and to provide access to a store of usernames and passwords which are then used in the respective authentication schemes.
Generally, all authentication schemes work with both proxies and servers. Some (basic and digest) can be used simultaneously with proxies and servers. See below for how to distinguish between proxy and server authentication.
How to use the Authenticator class
Authenticator is an abstract class which is extended by applications and once installed, is invoked to obtain usernames and passwords for authentication interactions.
Extending java.net.Authenticator
Application code must override the getPasswordAuthentication() method. Note, the method is not abstract, and the default implementation does nothing. The following is a minimal example:
class MyAuthenticator extends Authenticator {
public PasswordAuthentication getPasswordAuthentication () {
return new PasswordAuthentication ("user", "password".toCharArray());
}
}
This simple example returns the username "user" and a password for every HTTP authentication interaction. A more realistic example would use the other methods of java.net.Authenticator to get more information about the HTTP request that needs to be authenticated. Any of the following methods may be called by the implementation of getPasswordAuthentication() in order to decide how to handle each request for credentials.
- getRequestingHost()
- getRequestingPort()
- getRequestingPrompt()
- getRequestingProtocol()
- getRequestingScheme()
- getRequestingURL()
- getRequestingSite()
- getRequestorType(). Returns whether requestor is a proxy or server.
Enabling authentication
Having defined a suitable authenticator implementation class, authentication is enabled by calling
Authenticator.setDefault (authinstance);
where authinstance is an instance of the declared implementation class. If this is not called, then authentication is disabled, and server authentication errors will be returned to user code via IOException objects. Once installed, the http implementation will try to authenticate automatically where possible (via cached credentials, or credentials that can be acquired from the system). If the correct credentials are not available then the user's authenticator is invoked to provide them.
Controlling which authentication scheme is used
When a server needs a client to authenticate, it may propose a number of schemes to the client (for example digest and ntlm) and the client may choose from among them. Normally, applications do not care which scheme is used to and the implementation automatically chooses the strongest (most secure) protocol transparently.
If the user needs to ensure that a particular scheme is used, then the following system property can be set to modify the default behavior.
-Dhttp.auth.preference="scheme"
-D is specified if the property is being set on the command line. "http.auth.preference" is the property name, and scheme is the name of the scheme to use. If the server does not include this scheme in its list of proposed schemes, then the default choice is made.
Details of each authentication scheme
Http Basic
Basic authentication is a simple and not very secure authentication scheme which is defined in RFC 2317. The username and password are encoded in base 64 and are therefore easily obtainable by anyone who has access to the packet data. The security of basic authentication can be improved when used with HTTPS, thus encrypting the request and response.
The getRequestingPrompt() method returns the Basic authentication realm as provided by the server.
Http digest
Digest is a relatively secure scheme based on cryptographic hashes of the username and password, using the MD5 hash algorithm. Digest also provides the ability for the server to prove to the client that it also knows the shared secret (password). This behavior is normally disabled, because not all servers support it. This can be switched on with the following system properties:
-Dhttp.auth.digest.validateServer="true"
-Dhttp.auth.digest.validateProxy="true"
The getRequestingPrompt() method returns the Digest authentication realm as provided by the server.
NTLM
NTLM is a scheme defined by Microsoft. It is more secure scheme than Basic, but less secure than Digest. NTLM can be used with proxies or servers, but not with both at the same time. If a proxy is being used, then it cannot be used for server authentication. This is because the protocol actually authenticates the TCP connection rather than the individual HTTP interactions.
On Microsoft Windows platforms, NTLM authentication attempts to acquire the user credentials from the system without prompting the user's authenticator object. If these credentials are not accepted by the server then the user's authenticator will be called.
Because the Authenticator class was defined prior to NTLM being supported, it was not possible to add support in the API for the NTLM domain field. There are three options for specifying the domain:
- Do not specify it. In some environments, the domain is not actually required and the application need not specify it.
- The domain name can be encoded within the username by prefixing the domain name followed by a back-slash '\' before the username. With this method, existing applications that use the Authenticator class do not need to be modified, so long as users are made aware that this notation must be used.
- If a domain name is not specified as in method 2) and the system property "http.auth.ntlm.domain" is defined, then the value of this property will be used as the domain name.
Http Negotiate (SPNEGO)
Negotiate is a scheme which potentially allows any GSS authentication mechanism to be used as a HTTP authentication protocol. Currently, the scheme only supports Kerberos and NTLM. NTLM has already been described above, so this section only describes how to set up Kerberos for Http authentication.
Kerberos 5 Configuration
Since the SPNEGO mechanism will call JGSS, which in turns calls the Kerberos V5 login module to do real works. Kerberos 5 configurations are needed. which includes:
- Some way to provide Kerberos configurations. This can be achieved with the Java system property
java.security.krb5.conf. For example:
java -Djava.security.krb5.conf=krb5.conf \
-Djavax.security.auth.useSubjectCredsOnly=false \
ClassName
- A JAAS config file denoting what login module to use. HTTP SPNEGO codes will look for the standard entry named
com.sun.security.jgss.krb5.initiate.
For example, you can provide a file spnegoLogin.conf:
com.sun.security.jgss.krb5.initiate {
com.sun.security.auth.module.Krb5LoginModule
required useTicketCache=true;
};
and run java with:
java -Djava.security.krb5.conf=krb5.conf \
-Djava.security.auth.login.config=spnegoLogin.conf \
-Djavax.security.auth.useSubjectCredsOnly=false \
ClassName
Username and Password Retrieval
Just like any other HTTP authentication scheme, the client can provide a customized java.net.Authenticator to feed username and password to the HTTP SPNEGO module if they are needed (i.e. there is no credential cache available). The only authentication information needed to be checked in your Authenticator is the scheme which can be retrieved with getRequestingScheme(). The value should be "Negotiate". This means your Authenticator implementation will look like:
class MyAuthenticator extends Authenticator {
public PasswordAuthentication getPasswordAuthentication () {
if (getRequestingScheme().equalsIgnoreCase("negotiate")) {
String krb5user;
char[] krb5pass;
// get krb5user and krb5pass in your own way
....
return (new PasswordAuthentication (krb5user,
krb5pass));
} else {
....
}
}
}
Attention : According to the specification of java.net.Authenticator, it's designed to get the username and password at the same time, so do not specify principal=xxx in the JAAS config file.
Scheme Preference
The client can still provide system property http.auth.preference to denote that a certain scheme should always be used as long as the server request for it. You can use "SPNEGO" or "Kerberos" for this system property. "SPNEGO" means you prefer to response the Negotiate scheme using the GSS/SPNEGO mechanism; "Kerberos" means you prefer to response the Negotiate scheme using the GSS/Kerberos mechanism. Normally, when authenticating against a Microsoft product, you can use "SPNEGO". The value "Kerberos" also works for Microsoft servers. It's only needed when you encounter a server which knows Negotiate but doesn't know about SPNEGO. If http.auth.preference is not set, the internal order choosen is:
- GSS/SPNEGO -> Digest -> NTLM -> Basic
Noticed that Kerberos does not appear in this list, since whenever Negotiate is supported, GSS/SPNEGO is always chosen.
Fallback
If the server has provided more than one authentication schemes (including Negotiate), according to the processing order mentioned in the last section, Java will try to challenge the Negotiate scheme. However, if the protocol cannot be established successfully (e.g. The kerberos configuration is not correct, or the server's hostname is not recorded in the KDC principal DB, or the username and password provided by Authenticator is wrong), then the 2nd strongest scheme will be automatically used. Attention : If http.auth.preference is set to SPNEGO or Kerberos, then we assume you only want to try the Negotiate scheme even if it fails. we won't fallback to any other scheme and your program will result in throwing an IOException saying it receives a 401 or 407 error from the HTTP response.
Example
Suppose you have an IIS Server running on a Windows Server within an Active Directory. A web page on this server is configured to be protected by Integrated Windows Authentication. This means the server will prompt for both Negotiate and NTLM authentication.
You need to prepare these files to get the protected file:
Code listing for RunHttpSpnego.java
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.net.URL; public class RunHttpSpnego { static final String kuser = "username"; // your account name
static final String kpass = password; // retrieve password for your account static class MyAuthenticator extends Authenticator {
public PasswordAuthentication getPasswordAuthentication() {
// I haven't checked getRequestingScheme() here, since for NTLM
// and Negotiate, the usrname and password are all the same.
System.err.println("Feeding username and password for " + getRequestingScheme());
return (new PasswordAuthentication(kuser, kpass.toCharArray()));
}
} public static void main(String[] args) throws Exception {
Authenticator.setDefault(new MyAuthenticator());
URL url = new URL(args[0]);
InputStream ins = url.openConnection().getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(ins));
String str;
while((str = reader.readLine()) != null)
System.out.println(str);
}
}
Code listing for krb5.conf
[libdefaults]
default_realm = AD.LOCAL
[realms]
AD.LOCAL = {
kdc = kdc.ad.local
}
Code listing for login.conf
com.sun.security.jgss.krb5.initiate {
com.sun.security.auth.module.Krb5LoginModule required doNotPrompt=false useTicketCache=true;
};
Then, compile RunHttpSpnego.java and run:
java -Djava.security.krb5.conf=krb5.conf \
-Djava.security.auth.login.config=login.conf \
-Djavax.security.auth.useSubjectCredsOnly=false \
RunHttpSpnego \
http://www.ad.local/hello/hello.html
You will see:
Feeding username and password for Negotiate
<h1>Hello, You got me!</h1>
In fact, if you are running on a Windows machine as a domain user, or, you are running on a Linux or Solaris machine that has already issued the kinit command and got the credential cache. The class MyAuthenticator will be completely ignored, and the output will be simply
<h1>Hello, You got me!</h1>
which shows the username and password are not consulted. This is the so-called Single Sign-On. Also, You can just run
java RunHttpSpnego \
http://www.ad.local/hello/hello.html
to see how the fallback is done, in which case you will see
Feeding username and password for ntlm
<h1>Hello, You got me!</h1>
Http Authentication Java的更多相关文章
- Using JAAS Authentication in Java Clients---weblogic document
The following topics are covered in this section: JAAS and WebLogic Server JAAS Authentication Devel ...
- CAS单点登录和spring securtiy集成
说明:本文章主要建立在spring-security早已集成在系统中的前提下: 1.需要创建一个spring-security.xml文件并关联在applicationContext.xml文件中:& ...
- Maven Nexus Setup tutorial
Technorati 标签: maven,nexus 1. download the Nexus from website for free version: 2. Run the Command p ...
- 自学华为IoT物联网_10 IoT联接管理平台配置及开发实验1
点击返回自学华为IoT物流网 自学华为IoT物联网_10 IoT联接管理平台配置及开发实验1 实验1:OceanConnect平台实验 通过基本的编程操作与配置,帮助读者熟悉O ...
- 核心组件之SecurityContextHolder
作用:保留系统当前的安全上下文细节,其中就包括当前使用系统的用户的信息. 上下文细节怎么表示? 用SecurityContext对象来表示 每个用户都会有它的上下文,那这个Securi ...
- Spring Security教程(五):自定义过滤器从数据库从获取资源信息
在之前的几篇security教程中,资源和所对应的权限都是在xml中进行配置的,也就在http标签中配置intercept-url,试想要是配置的对象不多,那还好,但是平常实际开发中都往往是非常多的资 ...
- Spring Security教程(五)
在之前的几篇security教程中,资源和所对应的权限都是在xml中进行配置的,也就在http标签中配置intercept-url,试想要是配置的对象不多,那还好,但是平常实际开发中都往往是非常多的资 ...
- (转)Openfire 中SASL的认证方式之:PLAIN,DIGEST-MD5,anonymous
转:http://blog.csdn.net/coding_me/article/details/39524137 SASL 的认证方式包括: 1. PLAIN:plain是最简单的机制,但 ...
- spring security四种实现方式
spring security四种实现方式 spring(20) > 目录(?)[+] 最简单配置spring-securityxml实现1 实现UserDetailsService 实现动态过 ...
随机推荐
- Android 给TextView添加点击事件
首先设定TextView的clickable属性为true. 可以在布局文件中进行设定,比如: <TextView android:id="@+id/phone" andro ...
- rsyslog 直接kill进程,在重新启动会全部发送日志
<pre name="code" class="html">jrhapt11:/root# ps -ef | grep rsyslog root 8 ...
- COJ 0999 WZJ的数据结构(负一)
WZJ的数据结构(负一) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 输入N个模板串Pi和文本串T,输出每个模板串Pi在T ...
- 五大P2P平台费用一览
我看版上谈P2P的挺多的,正好我也投了点P2P, 今天看到一个不错的图 欢迎版上朋友讨论 -- 不忧不惧
- [LeetCode] Course Schedule I (207) & II (210) 解题思路
207. Course Schedule There are a total of n courses you have to take, labeled from 0 to n - 1. Some ...
- 查询Linux系统最后重启时间的三个方法
对于在Linux平台开发或运维的工程师来说,经常需要查询系统最后一次重启的时间,这篇文章将给大家介绍三种方法: 方法一:last命令 # last rebootreboot system boot 2 ...
- c语言学习笔记(1)——c语言的特点
一.c语言概述 1.为什么学习c语言? (1)c的起源和发展 第一代语言:机器语言 1101 第二代语言:汇编语言 add ax,bx; 第三代语言:高级语言 a+b; 结构化:c fortra ...
- [深入React] 2.综述
在开始本教程前,请先查看官方示例:https://github.com/facebook/react/archive/master.zip 里的 examples 目录. 学习react是一个循序渐进 ...
- (转)How to build an Apple Push Notification provider server (tutorial)
转自:https://blog.serverdensity.com/how-to-build-an-apple-push-notification-provider-server-tutorial/ ...
- MFC原创:三层架构01(人事管理系统)DAL
VC++/MFC Window编程原创教程文件夹 C++课程设计来着.但还没学过数据,也还没理解过三层架构,就把这个作业深化点来做了.尽管要做的这个人事管理系统看起来是挺简单的,无非就是处理员工信息. ...