java 资源访问权限_tomcat 访问资源限制

应该从web.xml中的login-config说起,他指明了用哪种认证,这个只有配一个,如果多个的话以后面的为准,该配置文件会被digester解析,login-config的配置会生成一个loginConfig对象放到webxml对象中成为一个属性,并通过configureContext()方法,使得loginConfig与context相联系

ContextConfig.configureStart()->authenticatorConfig()方法

authenticatorConfig() {

LoginConfig loginConfig = context.getLoginConfig();

SecurityConstraint constraints[] = context.findConstraints();

if (context.getIgnoreAnnotations() &&

(constraints == null || constraints.length ==0) &&

!context.getPreemptiveAuthentication())  {

return;

} else {

if (loginConfig == null) {

// Not metadata-complete or security constraints present, need

// an authenticator to support @ServletSecurity annotations

// and/or constraints

loginConfig = DUMMY_LOGIN_CONFIG;

context.setLoginConfig(loginConfig);

}

}

// Has an authenticator been configured already?

if (context.getAuthenticator() != null)

return;

if (!(context instanceof ContainerBase)) {

return;     // Cannot install a Valve even if it would be needed

}

// Has a Realm been configured for us to authenticate against?

if (context.getRealm() == null) {

log.error(sm.getString("contextConfig.missingRealm"));

ok = false;

return;

}

/*

* First check to see if there is a custom mapping for the login

* method. If so, use it. Otherwise, check if there is a mapping in

* org/apache/catalina/startup/Authenticators.properties.

*/

Valve authenticator = null;

if (customAuthenticators != null) {

authenticator = (Valve)

customAuthenticators.get(loginConfig.getAuthMethod());

}

if (authenticator == null) {

if (authenticators == null) {

log.error(sm.getString("contextConfig.authenticatorResources"));

ok = false;

return;

}

// Identify the class name of the Valve we should configure

String authenticatorName = null;

authenticatorName =

authenticators.getProperty(loginConfig.getAuthMethod());//根据loginConfig配置的方法名获取authenticatorName,这个authenticators是从ContextConfig的静态块中获得的,具体是读取了org/apache/catalina/startup/Authenticators.properties文件获得的

if (authenticatorName == null) {

log.error(sm.getString("contextConfig.authenticatorMissing",

loginConfig.getAuthMethod()));

ok = false;

return;

}

// Instantiate and install an Authenticator of the requested class

try {

Class> authenticatorClass = Class.forName(authenticatorName);//根据名字用反射创建认证器的实例

authenticator = (Valve) authenticatorClass.newInstance();

} catch (Throwable t) {

ExceptionUtils.handleThrowable(t);

log.error(sm.getString(

"contextConfig.authenticatorInstantiate",

authenticatorName),

t);

ok = false;

}

}

if (authenticator != null && context instanceof ContainerBase) {

Pipeline pipeline = ((ContainerBase) context).getPipeline();

if (pipeline != null) {

((ContainerBase) context).getPipeline().addValve(authenticator);//将认证器加入pipeline

if (log.isDebugEnabled()) {

log.debug(sm.getString(

"contextConfig.authenticatorConfigured",

loginConfig.getAuthMethod()));

}

}

}

}

当程序执行到context的pipeline中的valve时,AuthenticatorBase的invoke会被调用

public void invoke(Request request, Response response)

throws IOException, ServletException {

if (log.isDebugEnabled())

log.debug("Security checking request " +

request.getMethod() + " " + request.getRequestURI());

LoginConfig config = this.context.getLoginConfig();

// Have we got a cached authenticated Principal to record?

if (cache) {

Principal principal = request.getUserPrincipal();

if (principal == null) {

Session session = request.getSessionInternal(false);

if (session != null) {

principal = session.getPrincipal();

if (principal != null) {

if (log.isDebugEnabled())

log.debug("We have cached auth type " +

session.getAuthType() +

" for principal " +

session.getPrincipal());

request.setAuthType(session.getAuthType());

request.setUserPrincipal(principal);

}

}

}

}

// Special handling for form-based logins to deal with the case

// where the login form (and therefore the "j_security_check" URI

// to which it submits) might be outside the secured area

String contextPath = this.context.getPath();

String requestURI = request.getDecodedRequestURI();

if (requestURI.startsWith(contextPath) &&

requestURI.endsWith(Constants.FORM_ACTION)) {//form认证相关

if (!authenticate(request, response, config)) {

if (log.isDebugEnabled())

log.debug(" Failed authenticate() test ??" + requestURI );

return;

}

}

// Special handling for form-based logins to deal with the case where

// a resource is protected for some HTTP methods but not protected for

// GET which is used after authentication when redirecting to the

// protected resource.

// TODO: This is similar to the FormAuthenticator.matchRequest() logic

//       Is there a way to remove the duplication?

Session session = request.getSessionInternal(false);

if (session != null) {

SavedRequest savedRequest =

(SavedRequest) session.getNote(Constants.FORM_REQUEST_NOTE);//form认证相关

if (savedRequest != null) {

String decodedRequestURI = request.getDecodedRequestURI();

if (decodedRequestURI != null &&

decodedRequestURI.equals(

savedRequest.getDecodedRequestURI())) {

if (!authenticate(request, response)) {

if (log.isDebugEnabled()) {

log.debug(" Failed authenticate() test");

}

/*

* ASSERT: Authenticator already set the appropriate

* HTTP status code, so we do not have to do anything

* special

*/

return;

}

}

}

}

// The Servlet may specify security constraints through annotations.

// Ensure that they have been processed before constraints are checked

Wrapper wrapper = (Wrapper) request.getMappingData().wrapper;

if (wrapper != null) {

wrapper.servletSecurityAnnotationScan();

}

Realm realm = this.context.getRealm();

// Is this request URI subject to a security constraint?

SecurityConstraint [] constraints

= realm.findSecurityConstraints(request, this.context);//查找跟这个request相关的SecurityConstraints,这块我们会在web.xml中进行了配置,里配置了目录和相关的访问方法,存储在standardcontext对象中的constraints属性中,在这里会用request里的信息比如要访问的路径和方法(post or ...)与constraints中的路径比较,如果一样就认为该request有安全限制,需要进行后续的auth

if (constraints == null && !context.getPreemptiveAuthentication()) {

if (log.isDebugEnabled())

log.debug(" Not subject to any constraint");

getNext().invoke(request, response);

return;

}

// Make sure that constrained resources are not cached by web proxies

// or browsers as caching can provide a security hole

if (constraints != null && disableProxyCaching &&

!"POST".equalsIgnoreCase(request.getMethod())) {

if (securePagesWithPragma) {

// Note: These can cause problems with downloading files with IE

response.setHeader("Pragma", "No-cache");

response.setHeader("Cache-Control", "no-cache");

} else {

response.setHeader("Cache-Control", "private");

}

response.setHeader("Expires", DATE_ONE);

}

int i;

if (constraints != null) {

// Enforce any user data constraint for this security constraint

if (log.isDebugEnabled()) {

log.debug(" Calling hasUserDataPermission()");

}

if (!realm.hasUserDataPermission(request, response,

constraints)) {这里是验证request访问的数据是否有安全限制,在web.xml有相关配置(/security-constraint/user-data-constraint/transport-guarantee),如果配置的值不是NONE或者根本就没配置,那说明访问的数据需要加密,如果该访问是不https,会自动重定向https,重定向的端口是server.xml中connector中的属性redirectPort的值

if (log.isDebugEnabled()) {

log.debug(" Failed hasUserDataPermission() test");

}

/*

* ASSERT: Authenticator already set the appropriate

* HTTP status code, so we do not have to do anything special

*/

return;

}

}

// Since authenticate modifies the response on failure,

// we have to check for allow-from-all first.

boolean authRequired;

if (constraints == null) {

authRequired = false;

} else {

authRequired = true;

for(i=0; i < constraints.length && authRequired; i++) {

if(!constraints[i].getAuthConstraint()) {

authRequired = false;

} else if(!constraints[i].getAllRoles()) {

String [] roles = constraints[i].findAuthRoles();

if(roles == null || roles.length == 0) {

authRequired = false;

}

}

}

}

if (!authRequired && context.getPreemptiveAuthentication()) {

authRequired =

request.getCoyoteRequest().getMimeHeaders().getValue(

"authorization") != null;

}

if (!authRequired && context.getPreemptiveAuthentication() &&

HttpServletRequest.CLIENT_CERT_AUTH.equals(getAuthMethod())) {

X509Certificate[] certs = getRequestCertificates(request);

authRequired = certs != null && certs.length > 0;

}

if(authRequired) {

if (log.isDebugEnabled()) {

log.debug(" Calling authenticate()");

}

if (!authenticate(request, response, config)) {//这里调用AuthenticatorBase实现类的authenticate,比如BasicAuthenticator的authenticate

if (log.isDebugEnabled()) {

log.debug(" Failed authenticate() test");

}

/*

* ASSERT: Authenticator already set the appropriate

* HTTP status code, so we do not have to do anything

* special

*/

return;

}

}

if (constraints != null) {

if (log.isDebugEnabled()) {

log.debug(" Calling accessControl()");

}

if (!realm.hasResourcePermission(request, response,

constraints,

this.context)) {//这个是检查要访问的资源的用户角色是否满足之前配置的要求,该配置在web.xml中auth-constraint/role-name中配置的

if (log.isDebugEnabled()) {

log.debug(" Failed accessControl() test");

}

/*

* ASSERT: AccessControl method has already set the

* appropriate HTTP status code, so we do not have to do

* anything special

*/

return;

}

}

// Any and all specified constraints have been satisfied

if (log.isDebugEnabled()) {

log.debug(" Successfully passed all security constraints");

}

getNext().invoke(request, response);

}

简单说说server.xml中的realm,他就是存放用户密码等验证时用到的信息的对象,它可以添加到任意级别的container,并对所有下级container生效

只有代码中的principal我觉得应该叫他当事人,他就是经过认证的用户的信息,存在request和session中,formed验证应该会用到

web.xml中相关配置:

login-config中定义http认证方法

定义realm名字,感觉随便起就行

中说明需要加方法限制的路径,其实还可以配置访问这个路径的方法http-method,如果没配,就是所有方法都被限制,也可以配置http-method-omission,表示不受限制的方法,这个和http-method不能同时配,如果同时配,http-method优先

说明能够访问那个路径的角色

这里也定义了角色,是当中定义为*号时,会是使用这里定义的角色

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值