back to index
Using JAAS with Tomcat
Although it is possible to use JAAS within Tomcat as an authentication mechanism (JAASRealm), the flexibility of the JAAS framework is lost once the user is authenticated. This is because the principals are used to denote the concepts of "user" and "role", and are no longer available in the security context in which the webapp is executed. The result of the authentication is available only through request.getRemoteUser() and request.isUserInRole().
This reduces the JAAS framework for authorization purposes to a simple user/role system that loses its connection with the Java Security Policy. This tutorial's purpose is to put a full-blown JAAS authorisation implementation in place, using a few tricks to deal with some of Tomcat's idiosyncrasies.
Basic Design
The goal of the exercise is to be able to wrap the execution of our servlets/jsps in our own JAAS implementation, which allows us to enforce access control with a simple call in our code to AccessController.checkPermission(MyOwnPermission). We achieve this by wrapping each request in a security filter. This is configured in our web.xml. Most of this is covered in widely available JAAS tutorials on the net, so we only have some code fragments here.
web.xml
<filter>
<filter-name>SecurityFilter</filter-name>
<filter-class>security.SecurityFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SecurityFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Define a Security Constraint on this Application -->
<security-constraint>
<web-resource-collection>
<web-resource-name>Entire Application</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>authenticateduser</role-name>
</auth-constraint>
</security-constraint>
<!-- Define the Login Configuration for this Application -->
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>My Realm</realm-name>
</login-config>
login.conf
To start tomcat in security mode we call startup.sh with the -security flag. Furthermore we need to call our login module by setting $JVM_OPTS to something like -Djava.security.auth.login.config=/usr/local/tomcat/webapps/jaastest/WEB-INF/login.conf
Jaas {
security.HttpLoginModule required debug=true;
};
HttpLoginModule
public class HttpLoginModule implements LoginModule {
...
public boolean commit() throws LoginException {
if (debug)
System.err.println("HttpLoginModule: Commit");
if (!succeeded) {
// We didn't authenticate the user, but someone else did.
// Clean up our state, but don't add our principal to
// the subject
userName = null;
return false;
}
assignPrincipal(new UserPrincipal(userName));
//Based on the username, we can assign principals here
//Some examples for test....
assignPrincipal(new RolePrincipal("authenticateduser"));
assignPrincipal(new RolePrincipal("administrator"));
assignPrincipal(new CustomPrincipal("company1"));
// Clean up our internal state
userName = null;
commitSucceeded = true;
return true;
}
private void assignPrincipal(Principal p)
{
// Make sure we dont add duplicate principals
if (!subject.getPrincipals().contains(p)) {
subject.getPrincipals().add(p);
}
if(debug) System.out.println("Assigned principal "+p.getName()+" of type "+ p.getClass().getName() +" to user "+userName);
}
HttpAuthCallbackHandler
We have Tomcat or Apache do the authentication for us, so we just rely on request.getRemoteUser() to tell us the user name. Feel free to extend...
class HttpAuthCallbackHandler implements CallbackHandler {
private String userName;
public HttpAuthCallbackHandler (HttpServletRequest request) {
userName = request.getRemoteUser();
System.out.println("Remote user is: " + request.getRemoteUser());
}
public void handle(Callback[] cb) throws IOException, UnsupportedCallbackException {
for (int i = 0; i < cb.length; i++) {
if (cb[i] instanceof NameCallback) {
NameCallback nc = (NameCallback) cb[i];
nc.setName(userName);
} else throw new
UnsupportedCallbackException(cb[i], "HttpAuthCallbackHandler");
}
}
}
CustomPolicy
We install a Policy that adds Custom Permissions to the existing PermissionCollection
public class CustomPolicy extends Policy {
private Policy deferredPolicy;
public CustomPolicy(Policy p) {
deferredPolicy = p;
}
public PermissionCollection getPermissions(CodeSource cs) {
PermissionCollection pc = deferredPolicy.getPermissions(cs);
System.out.println("getPermissions was called for codesource");
return pc;
}
public PermissionCollection getPermissions(ProtectionDomain domain) {
PermissionCollection pc = deferredPolicy.getPermissions(domain);
System.out.println("getPermissions was called for domain");
Principal[] principals = domain.getPrincipals();
System.out.println("retrieved " + principals.length + " principals");
for (int i=0; i< principals.length; i++) {
Principal p = principals[i];
System.out.println("This is principal" + p);
CustomPermission[] pms = null;
if (p instanceof CustomPrincipal ) {
System.out.println(p.getName() + " is a CustomPrincipal");
// Get the permissions belonging to the principal here.
// Here we just add an example permission
CustomPermission[] test = { new CustomPermission("AccessToCompany1Building") };
pms = test;
} else {
System.out.println(p.getName() + " is not a CustomPrincipal");
}
// Nothing to do
if (pms == null) continue;
for(int j=0; j< pms.length; j++) {
System.out.println("Adding permission = " + pms[j]);
pc.add(pms[j]);
}
}
System.out.println(pc);
return pc;
}
public void refresh() {
deferredPolicy.refresh();
}
}
SecurityFilter
This is the core of our solution. We install our CustomPolicy here (note that this is definitely not redeployment-safe!). Note that we the feed our authenticated subject into the session. Tomcat then uses this subject when calling your servlets. This is the trick that makes the whole thing work; without it, the Subject is lost.
public class SecurityFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
Policy orgPolicy = Policy.getPolicy();
if (orgPolicy instanceof CustomPolicy) {
// we already did this once upon a time..
System.out.println("Policy is a CustomPolicy,we already did this once upon a time");
} else {
Policy.setPolicy(new CustomPolicy(orgPolicy));
System.out.println("Policy is not a CustomPolicy");
}
}
public void destroy() {
//config = null;
}
public void doFilter(ServletRequest sreq, ServletResponse sres,
FilterChain chain) throws IOException, ServletException {
System.out.println("Starting SecurityFilter.doFilter");
HttpServletResponse response = (HttpServletResponse)sres;
HttpServletRequest request = (HttpServletRequest)sreq;
HttpSession session = request.getSession(true);
Subject subject = (Subject)session.getAttribute("javax.security.auth.subject");
if (subject == null) {
subject = new Subject();
}
session.setAttribute("javax.security.auth.subject", subject);
LoginContext lc = null;
try {
lc = new LoginContext("Jaas", subject, new HttpAuthCallbackHandler(request));
System.out.println("established new logincontext");
} catch (LoginException le) {
le.printStackTrace();
response.sendError(HttpServletResponse.SC_FORBIDDEN, request.getRequestURI());
return;
}
try {
lc.login();
// if we return with no exception, authentication succeeded
} catch (Exception e) {
System.out.println("Login failed: " + e);
response.sendError(HttpServletResponse.SC_FORBIDDEN, request.getRequestURI());
return;
}
try {
System.out.println("Subject is " + lc.getSubject());
chain.doFilter(request, response);
} catch(SecurityException se) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, request.getRequestURI());
}
}
}
Testing it out
If you want to test your subject, a simple JSP like the one below is a great help
<%@page import="java.security.*" %>
<%@page import="javax.security.auth.*" %>
<html>
<h1>Hello World!</h1>
<pre>
<% Subject subject = Subject.getSubject(AccessController.getContext()); %>
<b>Subject</b> = <%= subject %>
-----------------------------------------------
<b>RemoteUser</b> = <%= request.getRemoteUser() %>
-----------------------------------------------
<%
out.print("Is user in role \"authenticateduser\"?: ");
if (request.isUserInRole("authenticateduser")) {
out.println("yes");
} else {
out.println("no");
}
%>
-----------------------------------------------
<b>Session Contents</b>
<%
java.util.Enumeration atts = session.getAttributeNames();
while (atts.hasMoreElements()) {
String elem = (String)atts.nextElement();
out.println(elem + " -> " + session.getAttribute(elem));
out.println( );
}
%>
</pre>
</html>
Copyright (c) 2004 Michiel Toneman : rot13(zvpuvry@xbcm.bet)
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. The full text of the license is found at: http://www.gnu.org/copyleft/fdl.html
分享到:
相关推荐
Chapter 1: Getting Started with Geronimo 7 Motivation behind the Geronimo project 7 Constituent projects 8 Apache Geronimo architecture 11 Downloading and running Apache Geronimo 12 Geronimo ...
人工智能、大语言模型相关学习资料
# 基于WebAssembly Micro Runtime的嵌入式应用框架 ## 项目简介 本项目基于WebAssembly Micro Runtime (WAMR),提供了一个轻量级的WebAssembly运行时环境,适用于嵌入式设备和物联网(IoT)应用。WAMR支持WebAssembly解释器、提前编译(AoT)和即时编译(JIT),并提供了丰富的应用框架和API,支持多种平台和架构。 ## 项目的主要特性和功能 iwasm VM核心 100符合W3C WebAssembly MVP标准。 小巧的运行时二进制大小(解释器85K,AoT 50K)和低内存占用。 通过AoT实现接近原生速度的执行效率。 自实现的模块加载器支持跨Linux、SGX和MCU系统运行。 支持内置libc子集或WASI标准libc。 可嵌入的C API支持。 支持将原生API导出到WebAssembly应用。 应用框架
芋道 yudao ruoyi-vue-pro crm sql , 更新时间 2024-09-30 ,可对应yudao版本2.4.1
微教育多校版小程序源码 开源版V3.12.75 大数据+营销插件+前端 版本号:3.12.75 – 全能版 修复部分用户统计图表不显示的问题 版本号:3.12.74 – 全能版 调整校园首页培训模式下 课程签到柱形图只统计线下课
人工智能、大语言模型相关学习资料
移动端项目-基于Android的随手记APP代码
python、yolo、pytorch
代码目录,traceId 关联,日志,网关
1、文件内容:systemd-devel-219-78.el7_9.9.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/systemd-devel-219-78.el7_9.9.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊
车牌识别项目
python、yolo、pytorch
系统选用B/S模式,后端应用springboot框架,前端应用vue框架, MySQL为后台数据库。 本系统基于java设计的各项功能,数据库服务器端采用了Mysql作为后台数据库,使Web与数据库紧密联系起来。 在设计过程中,充分保证了系统代码的良好可读性、实用性、易扩展性、通用性、便于后期维护、操作方便以及页面简洁等特点。
内容概要:本文详细介绍了PyTorch的张量和自动微分两大核心技术。首先,全面概述了PyTorch的特点及其在深度学习领域的优势,并讲解了PyTorch的安装和配置方法。接着,针对张量这一核心数据结构,阐述了张量的创建方式、常用的操作以及重要属性。再深入到自动微分子系统,解释了自动微分的概念及其工作机制,展示了如何利用计算图和反向传播算法来简化梯度计算。进一步地,在实战案例中演示了构建线性回归模型的全过程,从数据准备、模型定义、损失函数的选择直到训练模型。最后,介绍了一些高级进阶技巧,例如张量广播、拼接、切片和高阶导数的计算,为用户处理复杂任务提供了宝贵经验。 适合人群:有一定编程基础并希望深入理解和运用PyTorch进行深度学习项目的开发者、研究人员以及学生。 使用场景及目标:① 学习并掌握PyTorch框架,尤其是张量和自动微分模块的基础知识;② 结合具体示例理解和实施线性回归模型;③ 提升处理复杂深度学习任务的能力,比如通过高级张量操作优化性能、提高效率。 其他说明:本文不仅涵盖了理论知识还提供了大量的实践范例,能够帮助读者更快地上手和应用所学内容,适用于新手入门到中级水平用户的
本资源为安徽省土壤类型空间分布数据(共19类)。 编图所采用的制图单元有土类、亚类、土属、土种等,对照联合国粮农组织(FAO)土壤分类体系。 数据类型为标准shape格式。 可通过查阅“土壤分类体系”excel文件中的“土壤分类编码表”区分土壤类型。 属性表中的“SOIL_ID”与编码表中的“亚类”是一一对应的。 资源中还包含可编辑mxd文件,方便用户任意操作,同时包含标准TIF格式图片,可直接使用,还包含显示样式修改示意图,可自由选择自己喜欢的配色方案。
开发工具,可方便画原理图时,下载原理图及PCB 封装库
python、yolo、pytorch
vue项目,前端开发值得下载一看,绝对好看
p-07导入CSV文件.py
# 基于Arduino的RFID门禁系统 ## 项目简介 本项目是一个基于Arduino的全面RFID门禁系统,旨在实现安全的访问控制。系统使用MFRC522 RFID读取模块、用于控制门锁机制的伺服电机,以及LED和蜂鸣器为用户提供反馈,确保可靠且便捷的访问管理。 ## 项目的主要特性和功能 1. RFID认证系统读取RFID卡的唯一标识符(UID),并与预定义的授权ID列表进行验证。 2. 伺服电机控制伺服电机控制门的物理锁定机制,根据访问授权进行锁定或解锁操作。 3. 视觉和听觉反馈LED和蜂鸣器提供清晰的视觉和听觉指示,表明访问状态,提升用户体验。 4. 模块化和可定制性代码和硬件设置易于修改或扩展,可添加如键盘或生物识别传感器等额外功能。 ## 安装使用步骤 ### 步骤1收集组件 Arduino开发板(如Arduino Uno) MFRC522 RFID读取模块 伺服电机 LED和电阻 无源蜂鸣器 跳线