I used the spring security using saml from this https://github.com/spring-projects/spring-security-saml/tree/master/sample
Now I have my own JSP pages with controller, when I add it to the project, it is stating 404. when try to access http://localhost:2/SAMPLE/pop
My JSP at WEB-INF-jsp-pop.jsp
#Controller
public class ComCont {
#RequestMapping(value="/pop",method=RequestMethod.GET)
public String showHomePage(Map<Object, Object> model) {
System.out.println("gotach");
return "pop";
}
#RequestMapping(value="/hello",method=RequestMethod.GET)
public String showHomePage1(Map<Object, Object> model) {
System.out.println("gotach");
return "hello";
}
}
My servlet context is
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
securityContext.xml
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<!-- Enable auto-wiring -->
<context:annotation-config/>
<!-- Scan for auto-wiring classes in spring saml packages -->
<context:component-scan base-package="org.springframework.security.saml"/>
<!-- Unsecured pages -->
<security:http security="none" pattern="/favicon.ico"/>
<security:http security="none" pattern="/images/**"/>
<security:http security="none" pattern="/css/**"/>
<security:http security="none" pattern="/logout.jsp"/>
<!-- Security for the administration UI -->
<security:http pattern="/saml/web/**" use-expressions="false">
<security:access-denied-handler error-page="/saml/web/metadata/login"/>
<security:form-login login-processing-url="/saml/web/login" login-page="/saml/web/metadata/login" default-target-url="/saml/web/metadata"/>
<security:intercept-url pattern="/saml/web/metadata/login" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<security:intercept-url pattern="/saml/web/**" access="ROLE_ADMIN"/>
<security:custom-filter before="FIRST" ref="metadataGeneratorFilter"/>
</security:http>
<!-- Secured pages with SAML as entry point -->
<security:http entry-point-ref="samlEntryPoint" use-expressions="false">
<security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY"/>
<security:custom-filter before="FIRST" ref="metadataGeneratorFilter"/>
<security:custom-filter after="BASIC_AUTH_FILTER" ref="samlFilter"/>
</security:http>
<!-- Filters for processing of SAML messages -->
<bean id="samlFilter" class="org.springframework.security.web.FilterChainProxy">
<security:filter-chain-map request-matcher="ant">
<security:filter-chain pattern="/saml/login/**" filters="samlEntryPoint"/>
<security:filter-chain pattern="/saml/logout/**" filters="samlLogoutFilter"/>
<security:filter-chain pattern="/saml/metadata/**" filters="metadataDisplayFilter"/>
<security:filter-chain pattern="/saml/SSO/**" filters="samlWebSSOProcessingFilter"/>
<security:filter-chain pattern="/saml/SSOHoK/**" filters="samlWebSSOHoKProcessingFilter"/>
<security:filter-chain pattern="/saml/SingleLogout/**" filters="samlLogoutProcessingFilter"/>
<security:filter-chain pattern="/saml/discovery/**" filters="samlIDPDiscovery"/>
</security:filter-chain-map>
</bean>
<!-- Handler deciding where to redirect user after successful login -->
<bean id="successRedirectHandler"
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<property name="defaultTargetUrl" value="/"/>
</bean>
<!--
Use the following for interpreting RelayState coming from unsolicited response as redirect URL:
<bean id="successRedirectHandler" class="org.springframework.security.saml.SAMLRelayStateSuccessHandler">
<property name="defaultTargetUrl" value="/" />
</bean>
-->
<!-- Handler deciding where to redirect user after failed login -->
<bean id="failureRedirectHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="useForward" value="true"/>
<property name="defaultFailureUrl" value="/error.jsp"/>
</bean>
<!-- Handler for successful logout -->
<bean id="successLogoutHandler" class="org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler">
<property name="defaultTargetUrl" value="/logout.jsp"/>
</bean>
<security:authentication-manager alias="authenticationManager">
<!-- Register authentication manager for SAML provider -->
<security:authentication-provider ref="samlAuthenticationProvider"/>
<!-- Register authentication manager for administration UI -->
<security:authentication-provider>
<security:user-service id="adminInterfaceService">
<security:user name="admin" password="admin" authorities="ROLE_ADMIN"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
<!-- Logger for SAML messages and events -->
<bean id="samlLogger" class="org.springframework.security.saml.log.SAMLDefaultLogger"/>
<!-- Central storage of cryptographic keys -->
<bean id="keyManager" class="org.springframework.security.saml.key.JKSKeyManager">
<constructor-arg value="classpath:security/samlKeystore.jks"/>
<constructor-arg type="java.lang.String" value="nalle123"/>
<constructor-arg>
<map>
<entry key="apollo" value="nalle123"/>
</map>
</constructor-arg>
<constructor-arg type="java.lang.String" value="apollo"/>
</bean>
<!-- Entry point to initialize authentication, default values taken from properties file -->
<bean id="samlEntryPoint" class="org.springframework.security.saml.SAMLEntryPoint">
<property name="defaultProfileOptions">
<bean class="org.springframework.security.saml.websso.WebSSOProfileOptions">
<property name="includeScoping" value="false"/>
</bean>
</property>
</bean>
<!-- IDP Discovery Service -->
<bean id="samlIDPDiscovery" class="org.springframework.security.saml.SAMLDiscovery">
<property name="idpSelectionPath" value="/WEB-INF/security/idpSelection.jsp"/>
</bean>
<!-- Filter automatically generates default SP metadata -->
<bean id="metadataGeneratorFilter" class="org.springframework.security.saml.metadata.MetadataGeneratorFilter">
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.MetadataGenerator">
<property name="extendedMetadata">
<bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
<property name="idpDiscoveryEnabled" value="true"/>
</bean>
</property>
</bean>
</constructor-arg>
</bean>
<!-- The filter is waiting for connections on URL suffixed with filterSuffix and presents SP metadata there -->
<bean id="metadataDisplayFilter" class="org.springframework.security.saml.metadata.MetadataDisplayFilter"/>
<!-- Configure HTTP Client to accept certificates from the keystore for HTTPS verification -->
<!--
<bean class="org.springframework.security.saml.trust.httpclient.TLSProtocolConfigurer">
<property name="sslHostnameVerification" value="default"/>
</bean>
-->
<!-- IDP Metadata configuration - paths to metadata of IDPs in circle of trust is here -->
<bean id="metadata" class="org.springframework.security.saml.metadata.CachingMetadataManager">
<constructor-arg>
<list>
<!-- Example of classpath metadata with Extended Metadata -->
<bean class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate">
<constructor-arg>
<bean class="org.opensaml.saml2.metadata.provider.ResourceBackedMetadataProvider">
<constructor-arg>
<bean class="java.util.Timer"/>
</constructor-arg>
<constructor-arg>
<bean class="org.opensaml.util.resource.ClasspathResource">
<constructor-arg value="/metadata/idp.xml"/>
</bean>
</constructor-arg>
<property name="parserPool" ref="parserPool"/>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
</bean>
</constructor-arg>
</bean>
<!-- Example of HTTP metadata without Extended Metadata -->
<bean class="org.opensaml.saml2.metadata.provider.HTTPMetadataProvider">
<!-- URL containing the metadata -->
<constructor-arg>
<value type="java.lang.String">http://localhost:12/idp-meta.xml</value>
</constructor-arg>
<!-- Timeout for metadata loading in ms -->
<constructor-arg>
<value type="int">15000</value>
</constructor-arg>
<property name="parserPool" ref="parserPool"/>
</bean>
<!-- Example of file system metadata without Extended Metadata -->
<!--
<bean class="org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider">
<constructor-arg>
<value type="java.io.File">/usr/local/metadata/idp.xml</value>
</constructor-arg>
<property name="parserPool" ref="parserPool"/>
</bean>
-->
</list>
</constructor-arg>
<!-- OPTIONAL used when one of the metadata files contains information about this service provider -->
<!-- <property name="hostedSPName" value=""/> -->
<!-- OPTIONAL property: can tell the system which IDP should be used for authenticating user by default. -->
<!-- <property name="defaultIDP" value="http://localhost:8080/opensso"/> -->
</bean>
<!-- SAML Authentication Provider responsible for validating of received SAML messages -->
<bean id="samlAuthenticationProvider" class="org.springframework.security.saml.SAMLAuthenticationProvider">
<!-- OPTIONAL property: can be used to store/load user data after login -->
<!--
<property name="userDetails" ref="bean" />
-->
</bean>
<!-- Provider of default SAML Context -->
<bean id="contextProvider" class="org.springframework.security.saml.context.SAMLContextProviderImpl"/>
<!-- Processing filter for WebSSO profile messages -->
<bean id="samlWebSSOProcessingFilter" class="org.springframework.security.saml.SAMLProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationSuccessHandler" ref="successRedirectHandler"/>
<property name="authenticationFailureHandler" ref="failureRedirectHandler"/>
</bean>
<!-- Processing filter for WebSSO Holder-of-Key profile -->
<bean id="samlWebSSOHoKProcessingFilter" class="org.springframework.security.saml.SAMLWebSSOHoKProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationSuccessHandler" ref="successRedirectHandler"/>
<property name="authenticationFailureHandler" ref="failureRedirectHandler"/>
</bean>
<!-- Logout handler terminating local session -->
<bean id="logoutHandler"
class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler">
<property name="invalidateHttpSession" value="false"/>
</bean>
<!-- Override default logout processing filter with the one processing SAML messages -->
<bean id="samlLogoutFilter" class="org.springframework.security.saml.SAMLLogoutFilter">
<constructor-arg index="0" ref="successLogoutHandler"/>
<constructor-arg index="1" ref="logoutHandler"/>
<constructor-arg index="2" ref="logoutHandler"/>
</bean>
<!-- Filter processing incoming logout messages -->
<!-- First argument determines URL user will be redirected to after successful global logout -->
<bean id="samlLogoutProcessingFilter" class="org.springframework.security.saml.SAMLLogoutProcessingFilter">
<constructor-arg index="0" ref="successLogoutHandler"/>
<constructor-arg index="1" ref="logoutHandler"/>
</bean>
<!-- Class loading incoming SAML messages from httpRequest stream -->
<bean id="processor" class="org.springframework.security.saml.processor.SAMLProcessorImpl">
<constructor-arg>
<list>
<ref bean="redirectBinding"/>
<ref bean="postBinding"/>
<ref bean="artifactBinding"/>
<ref bean="soapBinding"/>
<ref bean="paosBinding"/>
</list>
</constructor-arg>
</bean>
<!-- SAML 2.0 WebSSO Assertion Consumer -->
<bean id="webSSOprofileConsumer" class="org.springframework.security.saml.websso.WebSSOProfileConsumerImpl"/>
<!-- SAML 2.0 Holder-of-Key WebSSO Assertion Consumer -->
<bean id="hokWebSSOprofileConsumer" class="org.springframework.security.saml.websso.WebSSOProfileConsumerHoKImpl"/>
<!-- SAML 2.0 Web SSO profile -->
<bean id="webSSOprofile" class="org.springframework.security.saml.websso.WebSSOProfileImpl"/>
<!-- SAML 2.0 Holder-of-Key Web SSO profile -->
<bean id="hokWebSSOProfile" class="org.springframework.security.saml.websso.WebSSOProfileConsumerHoKImpl"/>
<!-- SAML 2.0 ECP profile -->
<bean id="ecpprofile" class="org.springframework.security.saml.websso.WebSSOProfileECPImpl"/>
<!-- SAML 2.0 Logout Profile -->
<bean id="logoutprofile" class="org.springframework.security.saml.websso.SingleLogoutProfileImpl"/>
<!-- Bindings, encoders and decoders used for creating and parsing messages -->
<bean id="postBinding" class="org.springframework.security.saml.processor.HTTPPostBinding">
<constructor-arg ref="parserPool"/>
<constructor-arg ref="velocityEngine"/>
</bean>
<bean id="redirectBinding" class="org.springframework.security.saml.processor.HTTPRedirectDeflateBinding">
<constructor-arg ref="parserPool"/>
</bean>
<bean id="artifactBinding" class="org.springframework.security.saml.processor.HTTPArtifactBinding">
<constructor-arg ref="parserPool"/>
<constructor-arg ref="velocityEngine"/>
<constructor-arg>
<bean class="org.springframework.security.saml.websso.ArtifactResolutionProfileImpl">
<constructor-arg>
<bean class="org.apache.commons.httpclient.HttpClient">
<constructor-arg>
<bean class="org.apache.commons.httpclient.MultiThreadedHttpConnectionManager"/>
</constructor-arg>
</bean>
</constructor-arg>
<property name="processor">
<bean class="org.springframework.security.saml.processor.SAMLProcessorImpl">
<constructor-arg ref="soapBinding"/>
</bean>
</property>
</bean>
</constructor-arg>
</bean>
<bean id="soapBinding" class="org.springframework.security.saml.processor.HTTPSOAP11Binding">
<constructor-arg ref="parserPool"/>
</bean>
<bean id="paosBinding" class="org.springframework.security.saml.processor.HTTPPAOS11Binding">
<constructor-arg ref="parserPool"/>
</bean>
<!-- Initialization of OpenSAML library-->
<bean class="org.springframework.security.saml.SAMLBootstrap"/>
<!-- Initialization of the velocity engine -->
<bean id="velocityEngine" class="org.springframework.security.saml.util.VelocityFactory" factory-method="getEngine"/>
<!-- XML parser pool needed for OpenSAML parsing -->
<bean id="parserPool" class="org.opensaml.xml.parse.StaticBasicParserPool" init-method="initialize">
<property name="builderFeatures">
<map>
<entry key="http://apache.org/xml/features/dom/defer-node-expansion" value="false"/>
</map>
</property>
</bean>
<bean id="parserPoolHolder" class="org.springframework.security.saml.parser.ParserPoolHolder"/>
</beans>
web.xml
<servlet>
<servlet-name>saml</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>saml</servlet-name>
<url-pattern>/saml/web/*</url-pattern>
</servlet-mapping>
<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>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
What is I'm missing here? I'm new to Spring MVC. I know some basics.
URL pattern Syntax :
http://localhost:2/{Your project_name}/{url-pattern}/{jsp name}
Try to hit this url,
http://localhost:2/SAMPLE/saml/web/pop
else, Change your dispatcher-servlet Servlet mapping to like this,
<servlet-mapping>
<servlet-name>saml</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Now try this url, http://localhost:2/SAMPLE/pop
Change your Controller RequestMapping to like this,
#Controller
public class ComCont {
#RequestMapping(value="/pop",method=RequestMethod.GET)
public String showHomePage(Map<Object, Object> model) {
System.out.println("gotach");
return "pop";
}
}
Based on the content you have provided for web.xml and securityContext.xml, they looks fine, so doesn't look like filter chain issue. Moreover you are getting 404 which means there is some issue with URL, if you were getting 5xx then it could have been because of some server issue like filter chain. Or 403 if it was because of security or access issue. Below are details on resolution:
Assuming you do have (must be having) saml-servlet.xml, use below instead of what you have provided:
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
Based on above, you can understand (I think you are already doing) that you need to have your JSP's in /WEB-INF/jsp/
I am not sure what you are trying to achieve from your controller code but if you are trying to render your pop.jsp from the URL you mentioned then use below code in controller:
#RequestMapping(value="/pop",method=RequestMethod.GET)
public ModelAndView showHomePage(ModelMap model, HttpServletRequest request) {
System.out.println("I am in pop .. Lets rock ..");
return new ModelAndView("pop", "pop", "I am coming from controller");
}
Three arguments to ModelAndView constructor
Name of JSP, this case Spring will resolve it as pop.jsp and should be located under /WEB-INF/jsp/
Name of the object you want to pass to the JSP page, in this case name of the object is "pop", so you can use ${pop} in your JSP and you will see "I am coming from controller" getting rendered. This is just a String but you can pass a POJO which can be accessed using JSON notation in your JSP.
Actual object, String in this case.
Now, coming to your URL - http://localhost:2/SAMPLE/pop, I am pretty sure that you know this but I feel responsible to cover this, so - your WAR file name should be SAMPLE.war because that's your web context. If it is not then you have to use same name, lets say for springapp.war, your URL will be http://localhost:2/springapp. This is basic part of your URL.
Now you were using http://localhost:2/SAMPLE/pop which by all means is incorrect because your DispatcherServlet is configured for URL mapping of /saml/web/*. So, all your web request should have URL as http://localhost:2/SAMPLE/saml/web/. Whatever is the DispatcherServlet mapping should come after your URL context path - http://localhost:2/SAMPLE
Now, if you want to hit the /pop controller then you have start building your URL after DispatcherServlet mapping, so your URL will become http://localhost:2/SAMPLE/saml/web/pop.
If you use exact above URL and do the code modifications as I suggested then I am positive that your "pop.jsp" will be displayed.
Please note that your controller method is accepting only GET requests - RequestMethod.GET, so you have to hit the URL from browser. In case if you are sending Ajax POST requests from JSP then controller mapping should have RequestMethod.POST.
Also, please take care of using exact URL while taking care of slashes /
Related
I'm trying to setup a Spring project and want to use Spring Boot Actuator 2.1.6. I've found list to pure POJO configurations but my app is using a XML config and wanted to keep using XML.
I've tried using the configuration listed below but it doesn't work as it's based on an earlier version of Actuator than I'm using.
<bean name="endpointHandlerAdapter" class="org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerAdapter" />
<bean name="endpointHandlerMapping" class="org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping" />
<bean class="org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration$InfoPropertiesConfiguration" />
<bean name="beansEndpoint" class="org.springframework.boot.actuate.endpoint.BeansEndpoint" />
<beans>
<context:annotation-config />
<bean name="endpointAutoConfiguration" class="org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration"/>
</beans>
Using the config I get a number of class not found errors as the mvc package doesn't appear to exist in the newer version of Spring boot.
EDIT: Reading a bit more it seems that all of the available configurations are for the older Spring Boot Actuator 1 not the newer stuff. It looks like the amount of config that is needed has multiplied. Still interested in the answer but not holding out hope.
This is what we did for our spring + jersey project. As we are using an older version of spring (4.x), used spring boot actuator v1.5.22.RELEASE. Excluded autoconfigure dependency.
pom.xml snippet:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
<version>1.5.22.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</exclusion>
</exclusions>
</dependency>
XML config snippet:
<!-- Health -->
<bean id="orderedHealthAggregator" class="org.springframework.boot.actuate.health.OrderedHealthAggregator" />
<bean id="applicationHealthIndicator" class="org.springframework.boot.actuate.health.ApplicationHealthIndicator" />
<bean id="dataSourceHealthIndicator" class="org.springframework.boot.actuate.health.DataSourceHealthIndicator">
<constructor-arg index="0" ref="optimaxDataSource" />
</bean>
<bean id="jmsHealthIndicator" class="org.springframework.boot.actuate.health.JmsHealthIndicator">
<constructor-arg index="0" ref="connectionFactory" />
</bean>
<bean id="mailHealthIndicator" class="org.springframework.boot.actuate.health.MailHealthIndicator">
<constructor-arg index="0" ref="mailSender" />
</bean>
<!-- TODO: Set threshold value for disk space -->
<bean id="diskSpaceHealthIndicatorProperties" class="org.springframework.boot.actuate.health.DiskSpaceHealthIndicatorProperties" />
<bean id="diskSpaceHealthIndicator" class="org.springframework.boot.actuate.health.DiskSpaceHealthIndicator">
<constructor-arg index="0" ref="diskSpaceHealthIndicatorProperties" />
</bean>
<bean id="healthEndpoint" class="org.springframework.boot.actuate.endpoint.HealthEndpoint">
<constructor-arg index="0" ref="orderedHealthAggregator" />
<constructor-arg index="1" type="java.util.Map">
<map>
<entry key="application" value-ref="applicationHealthIndicator" />
<entry key="db" value-ref="dataSourceHealthIndicator" />
<entry key="jms" value-ref="jmsHealthIndicator" />
<entry key="mail" value-ref="mailHealthIndicator" />
<entry key="disk" value-ref="diskSpaceHealthIndicator" />
</map>
</constructor-arg>
</bean>
<!-- Git & Build Info -->
<bean id="gitClasspathProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="singleton" value="true" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:git.properties</value>
</list>
</property>
</bean>
<bean id="gitProperties" class="org.springframework.boot.info.GitProperties">
<constructor-arg index="0" ref="gitClasspathProperties" />
</bean>
<bean id="gitInfoContributor" class="org.springframework.boot.actuate.info.GitInfoContributor">
<constructor-arg index="0" ref="gitProperties" />
<constructor-arg index="1">
<value type="org.springframework.boot.actuate.info.InfoPropertiesInfoContributor.Mode">FULL</value>
</constructor-arg>
</bean>
<bean id="buildClasspathProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="singleton" value="true" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:build-info.properties</value>
</list>
</property>
</bean>
<bean id="buildProperties" class="org.springframework.boot.info.BuildProperties">
<constructor-arg index="0" ref="buildClasspathProperties" />
</bean>
<bean id="buildInfoContributor" class="org.springframework.boot.actuate.info.BuildInfoContributor">
<constructor-arg index="0" ref="buildProperties" />
</bean>
<bean id="infoEndpoint" class="org.springframework.boot.actuate.endpoint.InfoEndpoint">
<constructor-arg index="0" type="java.util.List">
<list>
<ref bean="gitInfoContributor" />
<ref bean="buildInfoContributor" />
</list>
</constructor-arg>
</bean>
<!-- Metrics -->
<bean id="systemPublicMetrics" class="org.springframework.boot.actuate.endpoint.SystemPublicMetrics" />
<bean id="metricsEndpoint" class="org.springframework.boot.actuate.endpoint.MetricsEndpoint">
<constructor-arg index="0" ref="systemPublicMetrics" />
</bean>
<!-- Beans -->
<bean id="beansEndpoint" class="org.springframework.boot.actuate.endpoint.BeansEndpoint" />
<!-- Env -->
<bean id="environmentEndpoint" class="org.springframework.boot.actuate.endpoint.EnvironmentEndpoint" />
<!-- Thread Dump -->
<bean id="threadDumpEndpoint" class="org.springframework.boot.actuate.endpoint.DumpEndpoint" />
Exposed the monitoring functionality via a Jersey resource.
#Path("/actuator")
public class ActuatorResource {
private static final ObjectMapper mapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
#Autowired
private HealthEndpoint healthEndpoint;
#GET
#Produces({ MediaType.APPLICATION_JSON })
#Path("/health")
#Transactional(readOnly = true)
public Response getHealth() throws JsonProcessingException {
return invoke(healthEndpoint);
}
private Response invoke(Endpoint<?> endpoint) {
try {
return Response.ok().entity(mapper.writeValueAsString(endpoint.invoke())).build();
} catch (Throwable t) {
logger.error("Error invoking endpoint : {}", endpoint.getClass().getName(), t);
return Response.serverError().entity("Request processing failed").build();
}
}
}
```
I'm trying to follow this example about Spring Security and adapt it to my needs but I'm having troubles with its configuration
I have a LoginService that looks like this:
// This example does not make sense of course but I'm just
// trying to make it work with #PreAuthorize("hasRole('ROLE_ADMIN')")
// and see an exception or something that lets me know that
// it is actually working ..
public class LoginService {
private final static Logger LOGGER = Logger.getLogger(LoginService.class.getName());
private AdministratorRepository administratorRepository;
public LoginService(DSLContext ctx) {
this.administratorRepository = new AdministratorRepository(ctx);
}
#Transactional
#PreAuthorize("hasRole('ROLE_ADMIN')")
public void login(String userId, String password) {
LOGGER.debug("Login for " + userId);
this.administratorRepository.login(userId, password);
}
}
and I am already initalizing this class in my applicationContext-jooq.xml like this:
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://localhost:5432/mz_db" />
<property name="username" value="postgres" />
<property name="password" value="1234" />
</bean>
<!-- Configure Spring's transaction manager to use a DataSource -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- Configure jOOQ's TransactionProvider as a proxy to Spring's transaction manager -->
<bean id="transactionProvider"
class="com.mz.server.web.SpringTransactionProvider">
</bean>
<!-- Configure jOOQ's ConnectionProvider to use Spring's TransactionAwareDataSourceProxy,
which can dynamically discover the transaction context -->
<bean id="transactionAwareDataSource"
class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
<constructor-arg ref="dataSource" />
</bean>
<bean class="org.jooq.impl.DataSourceConnectionProvider" name="connectionProvider">
<constructor-arg ref="transactionAwareDataSource" />
</bean>
<!-- Configure the DSL object, optionally overriding jOOQ Exceptions with Spring Exceptions -->
<bean id="dsl" class="org.jooq.impl.DefaultDSLContext">
<constructor-arg ref="config" />
</bean>
<!-- Invoking an internal, package-private constructor for the example
Implement your own Configuration for more reliable behaviour -->
<bean class="org.jooq.impl.DefaultConfiguration" name="config">
<property name="SQLDialect"><value type="org.jooq.SQLDialect">POSTGRES_9_4</value></property>
<property name="connectionProvider" ref="connectionProvider" />
<property name="transactionProvider" ref="transactionProvider" />
</bean>
<!-- BEGIN Services -->
<bean id="loginService" class="com.mz.server.web.service.LoginService">
<constructor-arg>
<ref bean="dsl" />
</constructor-arg>
</bean>
<!-- END Services -->
My problem is that I want loginService to be managed by Spring Security as well. This is my applicationContext-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-4.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd">
<global-method-security pre-post-annotations="enabled" secured-annotations="enabled" />
<http auto-config="true" >
<intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')" />
</http>
<authentication-manager >
<authentication-provider>
<user-service>
<user name="admin" password="admin" authorities="ROLE_ADMIN" />
</user-service>
</authentication-provider>
</authentication-manager>
<!-- <beans:bean name="loginService" class="com.mz.server.web.service.LoginService"/> -->
</beans:beans>
If I comment out
<beans:bean name="loginService" class="com.mz.server.web.service.LoginService"/>
I'm getting the error that there's no default constructor - which is true since this class is 1. Already instantiated and 2. Requires a DSLContext object as constructor parameter.
If I let it commented out just nothing happens. No exception of warning is shown. #PreAuthorize appears to be getting ignored ..
How can I resolve this issue?
You can add constructor injection into your XML configuration for the LoginService. Do you autowire DSLContext, too?
This line in your XML is invoking the default constructor:
<beans:bean name="loginService" class="com.mz.server.web.service.LoginService"/>
If you want to do constructor injection of the DSLContext it'd look like this:
<bean name="loginService" class="com.mz.server.web.service.LoginService">
<constructor-arg ref="dslContext"/>
</bean>
This assumes that the bean factory also has a bean for your DSLContext.
You can also try going all annotation or XML configuration, but not mixing and matching.
I want to expose a sample Spring web service which is authenticated using LDAP.
First, I have created the web service:
import javax.jws.WebMethod;
import javax.jws.WebService;
import com.domain.SampleEntity;
/**
* Actual web service implementation.
*
*/
#WebService
public class SampleEntityWebService {
/**
* Read and return SampleEntity by a supplied id.
*/
#WebMethod
public SampleEntityByIdResponse readSampleEntityById(Long id) {
SampleEntity sampleEntity = new SampleEntity();
sampleEntity.setId(id);
SampleEntityByIdResponse sampleEntityByIdResponse = new SampleEntityByIdResponse();
sampleEntityByIdResponse.setSampleEntity(sampleEntity);
return sampleEntityByIdResponse;
}
}
Web Service Provider configuration contains:
<?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:int="http://www.springframework.org/schema/integration"
xmlns:context="http://www.springframework.org/schema/context" xmlns:ws="http://www.springframework.org/schema/integration/ws"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:sws="http://www.springframework.org/schema/web-services"
xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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/integration/ws http://www.springframework.org/schema/integration/ws/spring-integration-ws-2.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/web-services http://www.springframework.org/schema/web-services/web-services-2.0.xsd
">
<!-- TOOD: Check if required or not -->
<!-- <bean id="simpleJaxWzServiceExporter"
class="org.springframework.remoting.jaxws.SimpleJaxWsServiceExporter">
<property name="baseAddress" value="${ws.base.url}" />
</bean> -->
<!-- <context:component-scan base-package="com.integration.ws.provider" /> -->
<!-- <context:property-placeholder location="classpath:META-INF/spring/web-service.properties" /> -->
<bean id="sampleEntityMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>com.integration.ws.provider.SampleEntityByIdRequest</value>
<value>com.integration.ws.provider.SampleEntityByIdResponse</value>
<value>com.domain.SampleEntity</value>
</list>
</property>
</bean>
<bean
class="org.springframework.ws.server.endpoint.mapping.UriEndpointMapping">
<property name="mappings">
<props>
<prop key="${ws.base.url}/sampleEntityById">sampleEntity-by-id-gateway</prop>
</props>
</property>
<property name="interceptors">
<list>
<ref local="wsSecurityInterceptor" />
</list>
</property>
</bean>
**<bean id="wsSecurityInterceptor"
class="org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor">
<property name="policyConfiguration" value="classpath:META-INF/securityPolicy.xml" />
<property name="callbackHandlers">
<list>
<ref bean="authenticationHandler"/>
</list>
</property>
</bean>**
<bean id="authenticationHandler"
class="org.springframework.ws.soap.security.xwss.callback.SpringDigestPasswordValidationCallbackHandler">
<property name="userDetailsService">
<bean class="org.springframework.security.core.userdetails.memory.InMemoryDaoImpl">
<property name="userMap">
<value>
${wsUserName}=${wsUserPassword},ROLE_USER
</value>
</property>
</bean>
</property>
</bean>
<ws:inbound-gateway id="sampleEntity-by-id-gateway"
request-channel="sampleEntityRequestById" marshaller="sampleEntityMarshaller"
unmarshaller="sampleEntityMarshaller" reply-channel="sampleEntityResponse" />
<int:channel id="sampleEntityRequestById" />
<int:channel id="sampleEntityResponse" />
<int:service-activator
expression="#sampleEntityWebService.readSampleEntityById(payload.id)"
input-channel="sampleEntityRequestById" output-channel="sampleEntityResponse" requires-reply="true"/>
<int:channel id="sampleEntitys" />
</beans>
The Security policy file referred contains:
<xwss:SecurityConfiguration dumpMessages="true" xmlns:xwss="http://java.sun.com/xml/ns/xwss/config">
<xwss:RequireUsernameToken passwordDigestRequired="true" nonceRequired="true"/>
</xwss:SecurityConfiguration>
The service is working fine as such. Now I want to authenticate the users who access this service using LDAP.
I am new to Spring web services and security. Can anyone please suggest about the configuration changes required to integrate a Spring web service with LDAP.
You can change the user details service from InMemoryDaoImpl to LdapUserDetailsService.
The configuration I can derive is:
<bean id="contextSource"
class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg value="ldap://monkeymachine:389/dc=springframework,dc=org"/>
<property name="userDn" value="cn=manager,dc=springframework,dc=org"/>
<property name="password" value="password"/>
</bean>
<bean id="ldapPopulator" class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
<constructor-arg ref="contextSource"/>
<constructor-arg value="ou=groups"/>
<property name="groupRoleAttribute" value="ou"/>
</bean>
<bean id="userSearch"
class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg index="0"
value="ou=People,o=MyCompany,o=Intranet" />
<constructor-arg index="1" value="(uid={0})" />
<constructor-arg index="2" ref="contextSource" />
</bean>
<bean id="authenticationHandler" class="org.springframework.ws.soap.security.xwss.callback.SpringDigestPasswordValidationCallbackHandler">
<property name="userDetailsService">
<bean class="org.springframework.security.ldap.userdetails.LdapUserDetailsService">
<constructor-arg ref="userSearch">
<constructor-arg ref="ldapPopulator">
</bean>
</property>
</bean>
Be in mind I haven't tried it yet, and most of the part I copied from another source. What you need is a UserDetailsService, and you just need to set that to the authenticationHandler. From the LdapUserDetailsService source code, it needs two constructor, LdapUserSearch, and LdapAuthoritiesPopulator. I googled an example on how to instantiate LdapUserSearch bean and found example from here. I found LdapPopulator bean example from the official documentation.
More details about Ldap Authentication with Spring Security can be found at the official documentation.
I hope you understand about LDAP, because I have no knowledge of LDAP. Good luck.
Details of the code that i have added for using Ajax Session time out, as described by BaluC
Faces-Config.xml
<factory>
<exception-handler-factory>org.omnifaces.exceptionhandler.FullAjaxExceptionHandlerFactory</exception-handler-factory>
</factory>
Web.xml
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/expired.xhtml</location>
</error-page>
application-config.xml
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<!-- override these for application-specific URLs if you like: -->
<property name="loginUrl" value="/index.xhtml" />
<property name="successUrl" value="/dashboard" />
<property name="unauthorizedUrl" value="/login" />
<property name="filters">
<util:map>
<entry key="authc">
<bean
class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter" />
</entry>
</util:map>
</property>
<property name="filterChainDefinitions">
<value>
[main]
user.loginUrl = /login.xhtml
[users]
admin = password
[urls]
/login.xhtml = user
/css/**=anon
/images/**=anon
/emailimages/**=anon
/login=anon
/test=anon
/sso=anon
/ssologin=anon
/**=authc
</value>
</property>
</bean>
<bean id="facesFilter" class="com.xxx.temp.FacesAjaxAwareUserFilter"></bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- <property name="sessionMode" value="native"/> -->
<property name="realms">
<list>
<ref bean="jdbcRealm" />
<ref bean="googleRealm" />
</list>
</property>
<!-- <property name="realms" ref="jdbcRealm googleRealm" /> -->
<property name="cacheManager" ref="cacheManager" />
<!-- <property name="sessionManager" ref="sessionManager"/> -->
</bean>
<!-- <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="/WEB-INF/ehcache.xml"/> </bean> -->
<bean id="passwordService"
class="org.apache.shiro.authc.credential.DefaultPasswordService">
</bean>
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManager" ref="ehCacheManager" />
</bean>
<!-- <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<property name="sessionDAO" ref="sessionDAO"/> </bean> -->
<bean id="ehCacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
<!-- <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO"/> -->
<bean id="jdbcRealm" class="com.xxx.domain.web.permissions.MyWebRealm">
</bean>
<bean id="googleRealm" class="com.xxx.domain.web.permissions.GoogleRealm">
<!-- <property name="dataSource" ref="dataSource" /> -->
<property name="credentialsMatcher"> <bean class="com.fetchinglife.domain.web.permissions.GoogleCredentialsMatcher"/> </property>
</bean>
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<bean
class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor" />
Added class file FacesAjaxAwareUserFilter
** code copied from BaluC blog **
Jar files added
omniface-1.7.jar
Added this in .xhtml file
xmlns:o="http://omnifaces.org/ui"
xmlns:of="http://omnifaces.org/functions"
came up with a warning
NLS missing message: CANNOT_FIND_FACELET_TAGLIB in:
org.eclipse.jst.jsf.core.validation.internal.facelet.messages
Current status:
No response found, page wont redirect on Session timeout ajax call.
Problem solved using this configuration.
faces-config.xml
<factory>
<exception-handler-factory>org.omnifaces.exceptionhandler.FullAjaxExceptionHandlerFactory</exception-handler-factory>
</factory>
Make Shiro JSF ajax aware by adding FacesAjaxAwareUserFilter
Added <bean class="com.xxx.custom.FacesAjaxAwareUserFilter" /> to util:map
application-config.xml
<util:map>
<entry key="authc">
<bean
class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter" />
<bean class="com.xxx.custom.FacesAjaxAwareUserFilter" />
</entry>
</util:map>
web.xml
Added error redirect page to the web.xml.
<error-page>
<error-code>500</error-code>
<location>/error.xhtml</location>
</error-page>
Mistake in my part.
There happens to be a SessionTimeoutFilter which was used for
redirecting non Ajax Timeout events, Due to some personal reasons,
they wont works peacefully together and i still don't know what
made the angry, when staying together. Any help on that is greatly appreciated.
This is the code i removed
<filter>
<filter-name>SessionTimeoutFilter</filter-name>
<filter-class>com.xxx.SessionTimeoutFilter</filter-class>
<init-param>
<param-name>SessionTimeoutRedirect</param-name>
<param-value>/login</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>SessionTimeoutFilter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
In my application users can manipulate with things, that linked only to them. All users have same role in spring security. So, to forbid user to view not his stuff, I need to implement in some controllers methods my own function to validate users rights.
public void securityValidation(User currentUser, Thing thing) {
if(!thing.has(currentUser)) {
log.warn("Security Control. User: " + user .getId());
}
}
I think It's not cool. It's hard to find in code is the method secured or not.
May be Spring has more elegant way for this task?
Or may be I can write my own annotation for securing methods? Do I need annotation processor for that?
You are referring to Domain Object Security, it is not part of the base security package. Spring Security ACL is what you need, with it you can assert ownership of actual items, for example user 123 can edit item 789. The code below makes sure the current user has admin rights over the entity he is editing:
#PreAuthorize("hasPermission(#entity, 'ADMINISTRATION')")
public SomeEntity update(SomeEntity entity) {
...
}
But keep in mind, you now have to manage those permissions and give/remove them to individual users. There is also a way to do it as part of a group. You can say user 123 and 345 belong to GROUP_SOME_ID and then if you give GROUP_SOME_ID admin permission over an object, users 123 and 345 will get them automatically. Removing user 123 from the group would automatically remove his permission as well.
---- UPDATE ------
Below is sample application context that wires up Spring Security ACL:
<?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:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="permissionEvaluator" ref="permissionEvaluator" />
</bean>
<!-- We'll rely on the standard AclPermissionEvaluator implementation -->
<bean class="org.springframework.security.acls.AclPermissionEvaluator" id="permissionEvaluator">
<constructor-arg ref="aclService" />
<property name="sidRetrievalStrategy" ref="sidRetrievalStrategy" />
<property name="permissionFactory" ref="permissionFactory"/>
</bean>
<bean class="org.springframework.security.acls.domain.SidRetrievalStrategyImpl" id="sidRetrievalStrategy" >
<constructor-arg ref="roleHierarchy" />
</bean>
<!-- Declare an acl service -->
<bean class="org.springframework.security.acls.jdbc.JdbcMutableAclService" id="aclService">
<constructor-arg ref="dataSource" />
<constructor-arg ref="lookupStrategy" />
<constructor-arg ref="aclCache" />
<property name="classIdentityQuery" value="select currval(pg_get_serial_sequence('acl_class', 'id'))" />
<property name="sidIdentityQuery" value="select currval(pg_get_serial_sequence('acl_sid', 'id'))" />
</bean>
<!-- Declare a lookup strategy -->
<bean id="lookupStrategy" class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
<constructor-arg ref="dataSource" />
<constructor-arg ref="aclCache" />
<constructor-arg ref="aclAuthorizationStrategy" />
<constructor-arg ref="permissionGrantingStrategy" />
<property name="permissionFactory" ref="permissionFactory"/>
</bean>
<bean id="permissionFactory" class="org.springframework.security.acls.domain.DefaultPermissionFactory" />
<!-- Declare an acl cache -->
<bean id="aclCache" class="org.springframework.security.acls.domain.SpringCacheBasedAclCache">
<constructor-arg>
<bean class="com.example.NoOpCache">
<constructor-arg value="aclCache" />
</bean>
</constructor-arg>
<constructor-arg ref="permissionGrantingStrategy" />
<constructor-arg ref="aclAuthorizationStrategy" />
</bean>
<!-- Declare an acl authorization strategy -->
<bean id="aclAuthorizationStrategy" class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
<constructor-arg>
<list>
<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<constructor-arg value="ROLE_ADMIN" />
</bean>
<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<constructor-arg value="ROLE_ADMIN" />
</bean>
<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<constructor-arg value="ROLE_ADMIN" />
</bean>
</list>
</constructor-arg>
</bean>
<bean id="permissionGrantingStrategy" class="org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy" >
<constructor-arg>
<bean class="org.springframework.security.acls.domain.ConsoleAuditLogger" />
</constructor-arg>
</bean>
<bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
<property name="hierarchy">
<value>
ROLE_USER > ROLE_ANONYMOUS
ROLE_SUPER_USER > ROLE_USER
ROLE_ADMIN > ROLE_SUPER_USER
</value>
</property>
</bean>
</beans>
#PreAuthorize("hasRole('ROLE_ADMIN')")
above any controller method you want to restrict to admins, for example.
Making sure you define methodSecurityExpressionHandler bean in web context.