I'm trying to configure spring secure annotations, I already managed to set spring security configuration in xml(configured by intercept-url elements), but now I'm want to use security annotations in my beans. But secured annotation is totaly ignored when try to access secured controller method without logging. Here is my controller bean:
package com.bill.controllers;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class MainController {
@Secured({"ROLE_USER"})
@RequestMapping("/index.html")
public String main(ModelMap model) {
model.addAttribute("test", "test");
return "main";
}
}
and login controller:
package com.bill.controllers;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class LoginController {
@RequestMapping("/login")
public String login(ModelMap model) {
return "login";
}
}
and configurations: web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>tests</display-name>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-servlet.xml,
/WEB-INF/spring-security.xml
</param-value>
</context-param>
<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>
</web-app>
spring-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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.bill" />
<context:annotation-config />
<!-- validation configuration -->
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
<mvc:annotation-driven validator="validator" />
<!-- view configuration for thymeleaf -->
<bean id="templateResolver"
class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
<property name="prefix" value="/WEB-INF/templates/" />
<property name="suffix" value=".html" />
<property name="templateMode" value="HTML5" />
<property name="characterEncoding" value="UTF-8" />
<property name="cacheable" value="false" />
</bean>
<bean id="templateEngine" class="org.thymeleaf.spring3.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
</bean>
<bean class="org.thymeleaf.spring3.view.ThymeleafViewResolver">
<property name="templateEngine" ref="templateEngine" />
<property name="characterEncoding" value="UTF-8" />
</bean>
<!-- messages configuration -->
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages/messages" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
<!-- internalization configuration -->
<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="language" />
</bean>
<bean
class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
<property name="interceptors">
<list>
<ref bean="localeChangeInterceptor" />
</list>
</property>
</bean>
<!-- datasource configuration for hibernate 4 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/bill" />
<property name="username" value="root" />
<property name="password" value="****" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.bill" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
and spring-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.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<http auto-config="true">
<form-login login-page="/login" default-target-url="/index.html" authentication-failure-url="/login" />
<logout logout-success-url="/index.html" />
<anonymous granted-authority="ROLE_GUEST" username="Guest"/>
</http>
<authentication-manager>
<authentication-provider>
<password-encoder hash="sha-256"/>
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="
select LOGIN, PASSWORD, 'true'
from USERS where LOGIN=?"
authorities-by-username-query="
select LOGIN, ROLE from USERS
where LOGIN=?"
/>
</authentication-provider>
</authentication-manager>
<global-method-security secured-annotations="enabled" />
</beans:beans>
If it will be needed I can also paste here my pom.xml, but I think that this is poblem with my configuration(because this example without security works fine, and with security configured in xml it also works). I will be realy glad if someone can tell me where is my mistake.
@PreAuthorize is different, it is more powerful than @Secured . The older @Secured annotations did not allow expressions to be used. @Secured("ROLE_ADMIN") annotation is the same as @PreAuthorize ("hasRole('ROLE_ADMIN')") . The @Secured({"ROLE_USER","ROLE_ADMIN") is considered as ROLE_USER OR ROLE_ADMIN.
The @PreAuthorize annotation checks the given expression before entering the method, whereas the @PostAuthorize annotation verifies it after the execution of the method and could alter the result.
The Secured annotation is used to define a list of security configuration attributes for business methods. This annotation can be used as a Java 5 alternative to XML configuration.
You have global method security enabled in the spring-security.xml
which is processed by the root web application context.
The controllers reside inside the dispatcher servlet context and are unaffected by the bean postprocessors of the root web app context.
So you have to declare <security:global-method-security secured-annotations="enabled" />
inside the dispatcher servlet context or use the web level spring security tags instead(which seems to be natural for the web pages).
See Difference between applicationContext.xml and spring-servlet.xml in Spring Framework
Technically the bean post processors(and therefore AOP tools too) work on per container basis - therefore the things like @Secured
or @Transactional
will only work in the same application context where the respective annotations - <security:global-method-security ../>
/ <tx:annotation-driven/>
have been applied.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With