java web 项目如何获取客户端登录帐号信息(用于SSO或其他)

前言

在java 中可以通过System 获取操作系统的相关信息。

类似:

String sys_user_name = System.getProperty("user.name");
或者

Map map = System.getenv();
String username = (String)map.get("USERNAME");
String compname = (String)map.get("COMPUTERNAME");
String userdomain =(String)map.get("USERDOMAIN");

但是这种方式获取的是服务端机器的信息。

举例来说,如果你使用的是Tomcat 的服务器, 那么, 以上方法获取的是Tomcat 所在机器的信息。

有的时候, 我们需要获取Web 客户端的一些信息, 用途可能是:

1. 记录Web项目的使用日志(哪个帐号在哪台机器上使用了哪个页面?)

2. 实现自动登录。

对于以上的需求1, 可能会说, 如果使用登录页面的帐号密码登录的话不就可以知道是谁登录了吗? 但并不是所有项目都是使用Form验证的方式, 可能是域帐号登录, 也可能是完全不需要登录的web 项目。


使用applet 获取

既然System 获取的是代码所在机器的信息,那么使用 applet 的方式不就可以了。

applet 获取客户端信息,再传递给服务端。

这种方式虽然可行, 但是客户端的浏览器安全的设置, JRE的安装与版本这些都制约着这种方式的有效性。

为了这样一个比较小的功能, 使用applet 显得太重了。


request.getRemoteUser

JSP的request 对象中有以下方法:

 out.println("remote address  "+request.getRemoteAddr());
 out.println("remote host  "+request.getRemoteHost());
 out.println("remote port "+request.getRemotePort());
 out.println("remote user  "+request.getRemoteUser());
以上看上去可以了。 但是 request.getRemoteUser 在有的时候返回的是null.

看一下getRemoteUser API的说明:

Returns the login of the user making this request, if the user has been authenticated, or null if the user has not been authenticated. Whether the user name is sent with each subsequent request depends on the browser and type of authentication. Same as the value of the CGI variable REMOTE_USER.

如果user 没有被认证的话, 返回的是null.又和http 的验证扯上了关系。


插入一段关于basic 认证的定义:

在HTTP协议进行通信的过程中,HTTP协议定义了基本认证过程以允许HTTP服务器对WEB浏览器进行用户身份证的方法,当一个客户端向HTTP服务 器进行数据请求时,如果客户端未被认证,则HTTP服务器将通过基本认证过程对客户端的用户名及密码进行验证,以决定用户是否合法。客户端在接收到HTTP服务器的身份认证要求后,会提示用户输入用户名及密码,然后将用户名及密码以BASE64加密,加密后的密文将附加于请求信息中, 如当用户名为anjuta,密码为:123456时,客户端将用户名和密码用“:”合并,并将合并后的字符串用BASE64加密为密文,并于每次请求数据 时,将密文附加于请求头(Request Header)中。HTTP服务器在每次收到请求包后,根据协议取得客户端附加的用户信息(BASE64加密的用户名和密码),解开请求包,对用户名及密码进行验证,如果用 户名及密码正确,则根据客户端请求,返回客户端所需要的数据;否则,返回错误代码或重新要求客户端提供用户名及密码。


不管以上一段是否看懂, 认证的目的就是让符合权限的人才能访问对应的页面和资源。在Tomcat 下可以如下方式来实现Basic 认证。

1. 在tomcat 的conf 目录下,修改 tomcat-users.xml 文件,增加以下内容到 tomcat-users标签中

<user username="oscar999" password="oscar999" roles="reader"/>

2.  在 tomcat 的webapps 目录下新建 auth 这样一个测试目录。

3.  在目录auth下, 新建chapter和WEB-INF两个目录。

4. 在 chapter下添加index.jsp,内容如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <meta name="author" content="oscar999">
  <title></title>
  </head>
  <body>
    This is Authenticate Test.
    <%
      out.println("remote user  "+request.getRemoteUser());
    %>
  </body>
</html>

5. 在WEB-INF下新加web.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app>
   <description>
        Authenticate Web Programming
   </description>
   <security-constraint>
        <web-resource-collection>
        <web-resource-name>
            Restricted Area
          </web-resource-name>
          <url-pattern>/chapter/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
          <role-name>tomcat</role-name>
          <role-name>reader</role-name>
        </auth-constraint>
   </security-constraint>
   <login-config>
       <auth-method>BASIC</auth-method>
       <realm-name>Authenticate yourself</realm-name>
    </login-config>   
</web-app>

好了, 启动tomcat ,访问 http://localhost:8080/auth/chapter/, 会出现:



要求输入用户名, 密码。

不输入,直接取消的话, 会出现 HTTP Status 401 错误。

正确输入 oscar999/oscar999 之后, 页面正常了。 而且request.getRemoteUser() 也抓到值了。


使用域帐号

以上是使用Basic 的方式进行认证, 哪些用户哪些权限需要配置在Tomcat 中。

但是有时候,希望直接通过域帐号进行验证。 也就是NTLM认证。

NTLM
默认设置(NTLM 协议)基于一种“提问 - 答复”机制来进行客户端验证。NTLM是NT LAN Manager的缩写,这也说明了协议的来源。NTLM 是 Windows NT 早期版本的标准安全协议,Windows 2000 支持 NTLM 是为了保持向后兼容。Windows 2000内置三种基本安全协议之一。


以上方式就可以获得登录域帐号等相关信息, 不过同样, 也会出现输入用户和密码的功能。

IE 和 Chrome 不会跳出输入用户名,密码窗口

<%
	String auth = request.getHeader("Authorization");
	if (auth == null) {
		response.setStatus(response.SC_UNAUTHORIZED);
		response.setHeader("WWW-Authenticate", "NTLM");
		response.flushBuffer();
		return;
	}
	if (auth.startsWith("NTLM ")) {
		byte[] msg = new sun.misc.BASE64Decoder().decodeBuffer(auth.substring(5));
		int off = 0, length, offset;
		if (msg[8] == 1) {
			byte z = 0;
			byte[] msg1 = { (byte) 'N', (byte) 'T', (byte) 'L', (byte) 'M', (byte) 'S', (byte) 'S', (byte) 'P',
					z, (byte) 2, z, z, z, z, z, z, z, (byte) 40, z, z, z, (byte) 1, (byte) 130, z, z, z,
					(byte) 2, (byte) 2, (byte) 2, z, z, z, z, z, z, z, z, z, z, z, z };
			response.setHeader("WWW-Authenticate", "NTLM " + new sun.misc.BASE64Encoder().encodeBuffer(msg1));
			response.sendError(response.SC_UNAUTHORIZED);
			return;
		} else if (msg[8] == 3) {
			off = 30;

			length = msg[off + 17] * 256 + msg[off + 16];
			offset = msg[off + 19] * 256 + msg[off + 18];
			String remoteHost = new String(msg, offset, length);

			length = msg[off + 1] * 256 + msg[off];
			offset = msg[off + 3] * 256 + msg[off + 2];
			String domain = new String(msg, offset, length);

			length = msg[off + 9] * 256 + msg[off + 8];
			offset = msg[off + 11] * 256 + msg[off + 10];
			String username = new String(msg, offset, length);

			out.println("Username:" + username + "<BR>");
			out.println("RemoteHost:" + remoteHost + "<BR>");
			out.println("Domain:" + domain + "<BR>");
		}
	}
%>



JS方式获取

除以上方式外, JS 也可以通过控件获取相关的信息。。

<script language="JavaScript">
var WshNetwork = new ActiveXObject("WScript.Network");
alert("Domain = " + WshNetwork.UserDomain);
alert("Computer Name = " + WshNetwork.ComputerName);
alert("User Name = " + WshNetwork.UserName);
</script>


不过这和IE等浏览器又密切相关了。
  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
Java Web项目中,要获取客户端登录帐号信息用于SSO,可以使用以下方法: 1. 使用Java Servlet API中的request对象获取登录用户信息。 在Servlet中,您可以使用HttpServletRequest对象的getRemoteUser()方法来获取登录用户的名称。例如: ```java request.getRemoteUser(); ``` 这将返回当前用户的名称,如果用户没有登录,则返回null。 2. 使用SSO框架获取登录用户信息 如果您正在使用SSO框架,那么您可以使用该框架提供的API来获取登录用户的信息。例如,如果您正在使用Spring Security,则可以使用SecurityContextHolder和Authentication对象来获取已认证的用户信息。例如: ```java Authentication auth = SecurityContextHolder.getContext().getAuthentication(); String username = auth.getName(); //获取当前用户名称 ``` 这将返回已经认证的用户的用户名。 3. 使用HTTP请求头获取登录用户信息 在某些情况下,您可以从HTTP请求头中获取登录用户的信息。例如,如果您正在使用基于标准HTTP身份验证的SSO,则可以使用Authorization头来获取用户名密码。例如: ```java String authHeader = request.getHeader("Authorization"); String[] credentials = new String(Base64.getDecoder().decode(authHeader.split(" ")[1])).split(":"); String username = credentials[0]; String password = credentials[1]; ``` 这将解码Authorization头并返回用户名密码。 总之,根据您的具体情况,可以选择使用不同的方法来获取登录用户信息。请记住,在使用SSO时,您需要确保在所有应用程序中使用相同的身份验证机制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

oscar999

送以玫瑰,手留余香

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值