How to integrate Spring Security and Struts2
Solution 1
Let's say you need to secure what's accessible on the /admin/*
path. You need to declare the Spring Security Filter in your web.xml
, the Struts filter should come after so that if you are accessing /admin
it will be Spring Security that handle the request first and will be able to let it pass or block it depending on the role of the user:
<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>/admin/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
You then declare your spring security context:
<http>
<intercept-url pattern="/*" filters="none" />
<intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<form-login login-page="/login" />
<logout logout-url="/logout" />
</http>
I propose that you use the struts2-convention
plugin so that URLs like /login
are bound automatically to a class named let's say com.foo.bar.actions.LoginAction
. Same for LogoutAction
Now what is under /admin/*
should be secured by Spring Security, and the rest should be forwarded directly to the Struts2 filter.
Finally, in your JSP you can check if someone is an Admin with:
<sec:authorize access="hasRole('ROLE_ADMIN')">
<p>you are an admin</p>
</sec:authorize>
The rest can be found in any Spring Security tutorial. What's really important is the order of the filters declaration, spring security must be first.
Edit: searching on google, there is also this link that can be of help for you.
Solution 2
This is actually very simple - Spring Security is web framework agnostic :)
You need to define Spring Security filter chain - this is a Java Filter that should be mapped to all requests. The filter will check if the path requires any privilages and if so checks if user is logged in and has those privilages.
Simple setup example.
web.xml (insert to your existing one, alongside struts config):
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:META-INF/spring/applicationContext-security.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<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>
Spring security configuration (in the file mentioned in web.xml in contextConfigLocation parameter):
<?xml version="1.0" encoding="UTF-8"?>
<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">
<http pattern="/js/**" security="none" />
<http pattern="/css/**" security="none" />
<http pattern="/images/**" security="none" />
<http auto-config="false" use-expressions="true">
<http-basic/>
<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<session-management session-fixation-protection="newSession" />
</http>
</beans:beans>
You may extend this as you wish - Spring's documentation is rather well written
You may go along an even simpler auto-config:
<http auto-config='true'>
<intercept-url pattern="/**" access="ROLE_USER" />
</http>
Above options secure your web-app per request path. You may want to secure the actions as well. Adding the below would get you going:
<global-method-security secured-annotations="enabled" pre-post-annotations="enabled" proxy-target-class = "true" />
Let me know what features you need and I can point you in a direction. Keep in mind that namespace config is not a silver bullet - if you need a very custom solution you might need to configure all the spring beans yourself, but the documentation explains this well.
user962206
Updated on June 29, 2022Comments
-
user962206 almost 2 years
I've done tons of googling regarding this issue and up to now I could not find any tutorial regarding integrating Struts2 and Spring Security.
My question is that How would I integrate Spring Security and Struts2?
Where I want certain actions or pages to be restricted, like the admin page/url should be accessed only by an administrator and other things like that if a user tried to accessed that page he or she would be redirected to another page.
-
user962206 over 11 yearswouldn't I annotate hasRole inside an action class?
-
Alex over 11 yearsIf you need to do it in a Java action class you can check it with
SecurityContextHolderAwareRequestWrapper.isUserInRole("ROLE_ADMIN")
-
user962206 over 11 yearsare there any tutorials regarding annotations? specifically for struts2?
-
Alex over 11 yearsthere is a plugin named
struts2-annotation
: struts.apache.org/2.2.1/docs/struts-2-annotations.html and also for spring security like@PreAuthorize
etc static.springsource.org/spring-security/site/docs/3.0.x/… -
user962206 over 11 yearsif I download the struts2-annotation will it automatically have that @PreAuthorize?
-
Alex over 11 yearsno
@PreAuthorize
is from spring security. Struts annotations are@Action
for example. -
user962206 over 11 yearsdo I nee another jar for @PreAuthorize maybe like Spring-struts2 annotation? or something like that?
-
user962206 over 11 yearsI'll look into it Spring Security first. then I'll get back here
-
Gnanz over 9 years@theadam spring's doc link broken
-
theadam over 9 years@granz Thanks for the tip, updated now. They have migrated the documentation. The link works now.