OK、「Spring は @Secured アノテーションを無視しています」という別の 1 つがあります。ここや他の場所で他の多くの解決策を読んだことがありますが、私の問題を解決するものはないようです。
Spring 3.1.1 および Spring Security 3.1.4 とともに、Netbeans 7.4beta を使用しています。
ログインしたユーザーに制限する必要があるコントローラーがあります。
package my.phonedirectory.mvc.controllers;
import javax.annotation.Resource;
import org.apache.log4j.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import my.phonedirectory.mvc.services.PhoneDirectoryService;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class IndexController {
protected static void debug(String msg) {
Logger logger = Logger.getLogger("Controller");
System.out.println("Logger Category: " + logger.getParent().toString());
logger.debug(new Object() { }.getClass().getEnclosingClass().getSimpleName() + ": " + msg);
}
@Resource(name="phoneDirectoryService")
PhoneDirectoryService phoneDirectoryService;
public void setPhoneDirectoryService(PhoneDirectoryService phoneDirectoryService) {
this.phoneDirectoryService = phoneDirectoryService;
}
@RequestMapping("/index.html")
@Secured("ROLE_USER")
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response)
throws Exception {
debug("handleRequestInternal");
String username;
SecurityContext sc = SecurityContextHolder.getContext();
Authentication auth = sc.getAuthentication();
if (auth == null) {
username = "SecurityContextHolder.getAuthentication() returned NULL";
} else {
Object principal = auth.getPrincipal();
if (principal == null) {
username = "SecurityContextHolder.getAuthentication().getPrincipal() returned NULL";
} else {
if (principal instanceof User) {
User user = (User)principal;
debug("User logged in: " + user.getUsername());
username = user.getUsername();
} else {
debug("No user logged in: " + principal.toString());
username = principal.toString();
}
}
}
ModelAndView mv = new ModelAndView("index");
mv.addObject("message", "Hello " + username);
return mv;
}
}
私のindex.jspファイルは次のとおりです。
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Phone Directory</title>
</head>
<body>
<h1> Welcome to the Phone Directory</h1>
<h2><%= (String)request.getAttribute("message") %></h2>
<p>
To see the Phone Directory, click <a href="list.html">HERE</a>.
</body>
</html>
localhost:8080/PhoneDirectory/index.html を読み込むと、次のようになります。
Welcome to the Phone Directory
Hello anonymousUser
To see the Phone Directory, click HERE.
ご覧のとおり、ログイン試行を強制するのではなく、匿名ユーザーが @Secured("ROLE_USER") によって保護されるはずのメソッドにアクセスできるようにします。
これは、Spring Security のデバッグ ロギングを有効にしたときにログに表示されるものです...
INFO: PhoneDirectory was successfully deployed in 5,899 milliseconds.
INFO: 16:15:25,889 DEBUG web.FilterChainProxy:337 - /index.html at position 1 of 10 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
INFO: 16:15:25,891 DEBUG context.HttpSessionSecurityContextRepository:139 - HttpSession returned null object for SPRING_SECURITY_CONTEXT
INFO: 16:15:25,891 DEBUG context.HttpSessionSecurityContextRepository:85 - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@36c63b9. A new one will be created.
INFO: 16:15:25,900 DEBUG web.FilterChainProxy:337 - /index.html at position 2 of 10 in additional filter chain; firing Filter: 'LogoutFilter'
INFO: 16:15:25,901 DEBUG web.FilterChainProxy:337 - /index.html at position 3 of 10 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
INFO: 16:15:25,901 DEBUG web.FilterChainProxy:337 - /index.html at position 4 of 10 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
INFO: 16:15:25,902 DEBUG web.FilterChainProxy:337 - /index.html at position 5 of 10 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
INFO: 16:15:25,902 DEBUG web.FilterChainProxy:337 - /index.html at position 6 of 10 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
INFO: 16:15:25,904 DEBUG web.FilterChainProxy:337 - /index.html at position 7 of 10 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
INFO: 16:15:25,907 DEBUG authentication.AnonymousAuthenticationFilter:102 - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@6faeba70: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@fffbcba8: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 33784332ecf862dfef93485b8bbf; Granted Authorities: ROLE_ANONYMOUS'
INFO: 16:15:25,907 DEBUG web.FilterChainProxy:337 - /index.html at position 8 of 10 in additional filter chain; firing Filter: 'SessionManagementFilter'
INFO: 16:15:25,908 DEBUG web.FilterChainProxy:337 - /index.html at position 9 of 10 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
INFO: 16:15:25,908 DEBUG web.FilterChainProxy:337 - /index.html at position 10 of 10 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
INFO: 16:15:25,909 DEBUG intercept.FilterSecurityInterceptor:185 - Public object - authentication not attempted
INFO: 16:15:25,910 DEBUG web.FilterChainProxy:323 - /index.html reached end of additional filter chain; proceeding with original chain
INFO: Logger Category: org.apache.log4j.spi.RootLogger@3fb9f67a
INFO: 16:15:25,967 DEBUG Controller:32 - IndexController: handleRequestInternal
INFO: Logger Category: org.apache.log4j.spi.RootLogger@3fb9f67a
INFO: 16:15:25,968 DEBUG Controller:32 - IndexController: No user logged in: anonymousUser
INFO: 16:15:25,976 DEBUG support.DefaultListableBeanFactory:1498 - Invoking afterPropertiesSet() on bean with name 'index'
INFO: 16:15:25,993 DEBUG support.DefaultListableBeanFactory:245 - Returning cached instance of singleton bean 'org.springframework.security.methodSecurityMetadataSourceAdvisor'
INFO: 16:15:26,151 DEBUG context.HttpSessionSecurityContextRepository:269 - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
INFO: 16:15:26,152 DEBUG context.HttpSessionSecurityContextRepository:269 - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
INFO: 16:15:26,155 DEBUG access.ExceptionTranslationFilter:115 - Chain processed normally
INFO: 16:15:26,156 DEBUG context.SecurityContextPersistenceFilter:97 - SecurityContextHolder now cleared, as request processing completed
これが私の web.xml ファイルです (注: 通常の applicationContext.xml と applicationContext-security.xml の名前を root-context.xml と root-security.xml に変更しました):
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/root-context.xml
/WEB-INF/root-security.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>phoneDirectory</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>phoneDirectory</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>redirect.jsp</welcome-file>
</welcome-file-list>
</web-app>
そして私の root-context.xml ファイル:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
</beans>
そして私の root-security.xml ファイル:
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<global-method-security secured-annotations="enabled" />
<http auto-config="true"
use-expressions="true"
access-denied-page="/PhoneDirectory/accessDenied" >
<form-login
login-page="/PhoneDirectory/login"
authentication-failure-url="/PhoneDirectory/login?error=true"
default-target-url="/PhoneDirectory/list"/>
<logout
invalidate-session="true"
logout-success-url="/PhoneDirectory/login"
logout-url="/PhoneDirectory/logout"/>
</http>
<authentication-manager>
<authentication-provider user-service-ref="userDetailsService">
</authentication-provider>
</authentication-manager>
<user-service id="userDetailsService">
<user name="user" password="user_password" authorities="ROLE_USER, ROLE_ADMIN" />
<user name="admin" password="admin_password" authorities="ROLE_USER" />
</user-service>
</beans:beans>
そして私の phoneDirectory-servlet.xml ファイル:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<security:global-method-security secured-annotations="enabled" />
<bean id="appService"
class="my.phonedirectory.mvc.services.PhoneDirectoryService">
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
<context:component-scan base-package="my.phonedirectory.mvc" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" />
</beans>
主なアドバイスは常に「最上位のapplicationContext.xml(または私の例ではroot-context.xml)ではなく、myApp-servlet.xmlファイルにタグを入れることです。しかし、それは私の問題を解決しませんでした. ..