Spring security with oauth2 adding additional parameters to authorization URL? - java

I have implemented Spring Security in my restful web service. In fact, I have to add an extra parameter with the request from client side and should fetch it from the service when request for authentication/accesstoken.
spring-security.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:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:sec="http://www.springframework.org/schema/security" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd ">
<!-- #author Nagesh.Chauhan(neel4soft#gmail.com) -->
<!-- This is default url to get a token from OAuth -->
<http pattern="/oauth/token" create-session="stateless"
authentication-manager-ref="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<!-- include this only if you need to authenticate clients via request
parameters -->
<custom-filter ref="clientCredentialsTokenEndpointFilter"
after="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<!-- This is where we tells spring security what URL should be protected
and what roles have access to them -->
<http pattern="/api/**" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/api/**" access="ROLE_APP" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="test" />
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="test/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="clientAuthenticationManager" />
</bean>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased"
xmlns="http://www.springframework.org/schema/beans">
<constructor-arg>
<list>
<bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" />
<bean class="org.springframework.security.access.vote.RoleVoter" />
<bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
</list>
</constructor-arg>
</bean>
<authentication-manager id="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<!-- Custom User details service which is provide the user data -->
<bean id="customUserDetailsService"
class="com.weekenter.www.service.impl.CustomUserDetailsService" />
<authentication-manager alias="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="customUserDetailsService">
<password-encoder hash="plaintext">
</password-encoder>
</authentication-provider>
</authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<!-- This defined token store, we have used inmemory tokenstore for now
but this can be changed to a user defined one -->
<bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore" />
<!-- This is where we defined token based configurations, token validity
and other things -->
<bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="accessTokenValiditySeconds" value="120" />
<property name="clientDetailsService" ref="clientDetails" />
</bean>
<bean id="userApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler">
<property name="tokenServices" ref="tokenServices" />
</bean>
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices"
user-approval-handler-ref="userApprovalHandler">
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<oauth:password />
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter"
resource-id="test" token-services-ref="tokenServices" />
<oauth:client-details-service id="clientDetails">
<!-- client -->
<oauth:client client-id="restapp"
authorized-grant-types="authorization_code,client_credentials"
authorities="ROLE_APP" scope="read,write,trust" secret="secret" />
<oauth:client client-id="restapp"
authorized-grant-types="password,authorization_code,refresh_token,implicit"
secret="restapp" authorities="ROLE_APP" />
</oauth:client-details-service>
<sec:global-method-security
pre-post-annotations="enabled" proxy-target-class="true">
<!--you could also wire in the expression handler up at the layer of the
http filters. See https://jira.springsource.org/browse/SEC-1452 -->
<sec:expression-handler ref="oauthExpressionHandler" />
</sec:global-method-security>
<oauth:expression-handler id="oauthExpressionHandler" />
<oauth:web-expression-handler id="oauthWebExpressionHandler" />
</beans>
CustomUserDetailsService
#Service
#Transactional(readOnly = true)
public class CustomUserDetailsService implements UserDetailsService {
#Autowired
private LoginDao loginDao;
public UserDetails loadUserByUsername(String login)
throws UsernameNotFoundException {
boolean enabled = true;
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
com.weekenter.www.entity.User user = null;
try {
user = loginDao.getUser(login);
if (user != null) {
if (user.getStatus().equals("1")) {
enabled = false;
}
} else {
throw new UsernameNotFoundException(login + " Not found !");
}
} catch (Exception ex) {
try {
throw new Exception(ex.getMessage());
} catch (Exception ex1) {
}
}
return new User(
user.getEmail(),
user.getPassword(),
enabled,
accountNonExpired,
credentialsNonExpired,
accountNonLocked,
getAuthorities()
);
}
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authList = getGrantedAuthorities(getRoles());
return authList;
}
public List<String> getRoles() {
List<String> roles = new ArrayList<String>();
roles.add("ROLE_APP");
return roles;
}
public static List<GrantedAuthority> getGrantedAuthorities(List<String> roles) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for (String role : roles) {
authorities.add(new SimpleGrantedAuthority(role));
}
return authorities;
}
}
Currently I am requesting with the URL:
http://localhost:8084/Domain/oauth/token?grant_type=password&client_id=restapp&client_secret=restapp&username=anoo#codelynks.com&password=mypass
And I will get the response
{
"access_token":"76e928b2-45e2-4283-88a4-6c01f41b51d3","token_type":"bearer","refresh_token":"8748e8ad-79c1-465d-94fe-13394eea370d","expires_in":119
}
I have to enhance it by adding additional parameter deviceToken.
And the URL would be:
http://localhost:8084/Domain/oauth/token?grant_type=password&client_id=restapp&client_secret=restapp&username=anoo#codelynks.com&password=mypass&deviceToken=something
I have treid by implementing UsernamePasswordAuthenticationFilter, but it didn't work. How can I get the deviceToken parameter from the web service without affecting the output?

http://localhost:8084/Domain/oauth/token?grant_type=password&client_id=restapp&client_secret=restapp&username=anoo#codelynks.com&password=mypass&additional_param=abc123
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
log.info("additional_param: " + request.getParameter("additional_param"));
log will show
additional_param: abc123

Although AOP is used when it comes to crosscutting concerns, this approach worked as expected and I think It is a valid approach.
#Aspect
public class Oauth2Aspect {
#AfterReturning("execution( * org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(..))")
public void executeAfterAuthentication() throws Exception {
System.out.println(":Authentication done");
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
System.out.println(":Authentication done " + request.getParameter("deviceInfo"));
}
}

Related

Spring security authentication fails

I am using Spring security version 3.1.4.RELEASE. When I try to login to the application I am getting an error. I have cross checked the credentials in DB. Even though the credentials are correct the system is not lettng me to login. Following the details of error and my configuration settings.
Getting following error while trying to login to the system:
web.security.auth.CustomUsernamePasswordAuthenticationFilter username is support
web.security.auth.CustomUsernamePasswordAuthenticationFilter password is [PROTECTED]
web.security.auth.CustomUsernamePasswordAuthenticationFilter authRequest is org.springframework.security.authentication.UsernamePasswordAuthenticationToken#4a159a52: Principal: support; Credentials: [PROTECTED]; Authenticated: false; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#0: RemoteIpAddress: 204.238.52.177; SessionId: 9B49838B0DF4224E169EAF425C0AABE9; Not granted any authorities
web.security.auth.CustomUsernamePasswordAuthenticationFilter Authentication manager was com.sun.proxy.$Proxy476
System.out loadUserByUsername support enter
org.springframework.security.authentication.event.LoggerListener Authentication event AuthenticationFailureServiceExceptionEvent: support; details: org.springframework.security.web.authentication.WebAuthenticationDetails#0: RemoteIpAddress: 204.238.52.177; SessionId: 9B49838B0DF4224E169EAF425C0AABE9; exception: null
Here I am getting the exception as null!
Config:
<authentication-manager alias="authenticationManager">
<authentication-provider ref="daoAuthenticationProvider" />
</authentication-manager>
<beans:bean id="plaintextPasswordEncoder" class="org.springframework.security.authentication.encoding.PlaintextPasswordEncoder" />
<beans:bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<beans:property name="userDetailsService" ref="daoUserDetailsService" />
<beans:property name="passwordEncoder" ref="plaintextPasswordEncoder" />
</beans:bean>
<beans:bean id="daoUserDetailsService" class="web.security.auth.DAOUserDetailsService">
<beans:property name="dataSource" ref="dataSource" />
</beans:bean>
<beans:bean id="dataSource" class="web.security.auth.DAODataSource" />
<beans:bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
<filter-chain-map request-matcher="ant">
<filter-chain pattern="/**" filters="channelProcessingFilter, SecurityContextPersistenceFilter, logoutFilter, authenticationFilter, anonymousAuthFilter, exceptionTranslationFilter, filterSecurityInterceptor" />
</filter-chain-map>
</beans:bean>
<beans:bean id="channelProcessingFilter" class="org.springframework.security.web.access.channel.ChannelProcessingFilter">
<beans:property name="channelDecisionManager" ref="channelDecisionManager"/>
<beans:property name="securityMetadataSource">
<filter-security-metadata-source request-matcher="ant">
<intercept-url pattern="/**" access="REQUIRES_SECURE_CHANNEL"/>
</filter-security-metadata-source>
</beans:property>
</beans:bean>
<beans:bean id="channelDecisionManager" class="org.springframework.security.web.access.channel.ChannelDecisionManagerImpl">
<beans:property name="channelProcessors">
<beans:list>
<beans:ref bean="secureChannelProcessor"/>
<beans:ref bean="insecureChannelProcessor"/>
</beans:list>
</beans:property>
</beans:bean>
<beans:bean id="secureChannelProcessor" class="org.springframework.security.web.access.channel.SecureChannelProcessor" />
<beans:bean id="insecureChannelProcessor" class="org.springframework.security.web.access.channel.InsecureChannelProcessor" />
<beans:bean id="SecurityContextPersistenceFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter" />
<beans:bean id="authenticationFilter" class="web.security.auth.CustomUsernamePasswordAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager"/>
<beans:property name="filterProcessesUrl" value="/j_spring_security_check"/>
<beans:property name="usernameParameter" value="username"/>
<beans:property name="passwordParameter" value="password"/>
</beans:bean>
<beans:bean id="anonymousAuthFilter" class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
<beans:property name="key" value="foobar"/>
<beans:property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
</beans:bean>
<beans:bean id="anonymousAuthenticationProvider" class="org.springframework.security.authentication.AnonymousAuthenticationProvider">
<beans:property name="key" value="foobar"/>
</beans:bean>
<beans:bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<beans:property name="authenticationManager" ref="authenticationManager"/>
<beans:property name="accessDecisionManager" ref="accessDecisionManager"/>
<beans:property name="securityMetadataSource">
<filter-security-metadata-source>
<intercept-url pattern="/LoginPage" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/LoginExpiredPage" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/wicket/bookmarkable/web.sec.pages.LoginExpiredPage" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/css/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/images/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/*.png" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/*.ico" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/wicket/resource/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY, IS_AUTHENTICATED_REMEMBERED"/>
</filter-security-metadata-source>
</beans:property>
</beans:bean>
<beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<beans:property name="decisionVoters">
<beans:list>
<beans:bean class="org.springframework.security.access.vote.RoleVoter">
<beans:property name="rolePrefix" value="ROLE_"/>
</beans:bean>
<beans:bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>
</beans:list>
</beans:property>
</beans:bean>
<beans:bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<beans:constructor-arg value="/" />
<beans:constructor-arg>
<beans:list>
<beans:bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</beans:list>
</beans:constructor-arg>
<beans:property name="filterProcessesUrl" value="/logout"/>
</beans:bean>
<beans:bean id="forceCookieUseFilter" class="web.security.ForceCookieUseFilter">
<beans:constructor-arg>
<beans:list>
<beans:bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</beans:list>
</beans:constructor-arg>
</beans:bean>
<beans:bean id="exceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
<beans:property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
<beans:property name="accessDeniedHandler" ref="accessDeniedHandler"/>
</beans:bean>
<beans:bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/LoginPage"/>
</beans:bean>
<beans:bean id="accessDeniedHandler" class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<beans:property name="errorPage" value="/accessDenied.htm"/>
</beans:bean>
<beans:bean id="loggerListener" class="org.springframework.security.authentication.event.LoggerListener"/>
AuthenticationFilter class as follows:
public class CustomUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username";
public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password";
public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";
private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
private boolean postOnly = true;
public CustomUsernamePasswordAuthenticationFilter() {
super("/j_spring_security_check");
}
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
String username = obtainUsername(request);
String password = obtainPassword(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
username = username.trim();
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
if(this.getAuthenticationManager()==null){
logger.info("Authentication manager is null.");
} else {
logger.info("Authentication manager was "+this.getAuthenticationManager().getClass().getName());
}
return this.getAuthenticationManager().authenticate(authRequest);
}
protected String obtainPassword(HttpServletRequest request) {
return request.getParameter(passwordParameter);
}
protected String obtainUsername(HttpServletRequest request) {
return request.getParameter(usernameParameter);
}
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
}
public void setUsernameParameter(String usernameParameter) {
this.usernameParameter = usernameParameter;
}
public void setPasswordParameter(String passwordParameter) {
this.passwordParameter = passwordParameter;
}
public void setPostOnly(boolean postOnly) {
this.postOnly = postOnly;
}
public final String getUsernameParameter() {
return usernameParameter;
}
public final String getPasswordParameter() {
return passwordParameter;
}
}
UserDetails class as follows:
public class DAOUserDetailsService implements UserDetailsService {
private DataSource dataSource;
public void setDataSource(DAODataSource dataSource) {
this.dataSource = dataSource;
}
public DAOUserDetailsService () { }
public DAOUserDetailsService (DAODataSource dataSource) {
this.dataSource = dataSource;
}
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
DataSource ds = dataSource;
PreparedStatement userStatement = null;
try {
Connection con = ds.getConnection();
String userQuery = "SELECT USER_ID, USER_PASSWORD, USER_ENABLED FROM USER WHERE USER_ID = ?";
userStatement = con.prepareStatement(userQuery);
userStatement.setString(0, username);
ResultSet userResults = userStatement.executeQuery();
if (userResults.next()) {
final SimpleGrantedAuthority supervisorAuthority = new SimpleGrantedAuthority(
"supervisor");
final SimpleGrantedAuthority userAuthority = new SimpleGrantedAuthority(
"user");
Collection<GrantedAuthority> authorityList = new ArrayList<GrantedAuthority>();
authorityList.add(supervisorAuthority);
authorityList.add(userAuthority);
return new User(userResults.getString(0), userResults.getString(1), authorityList);
}
throw new UsernameNotFoundException(username);
} catch (SQLException e) {
throw new UsernameNotFoundException(e.toString());
}
finally {
if (userStatement != null) {
try {
userStatement.close();
} catch (SQLException e) {
throw new UsernameNotFoundException(e.toString());
}
}
}
}
}
Kindly provide some idea on the issue.
Thanks in advance.
You can create your implementation of LoggerListener for investigate more the causes.
public class LoggerListener implements ApplicationListener<AbstractAuthorizationEvent> {
private static final Log logger = LogFactory.getLog(LoggerListener.class);
public void onApplicationEvent(AbstractAuthorizationEvent event) {
//investigation code
}
}
I had a very similar problem and the cause was one ClassCastException in other part of code, one controller.
In your class DAOUserDetailsService:
...
return new User(userResults.getString(0), userResults.getString(1), new ArrayList<GrantedAuthority>());
...
you return UserDeatils with empty authorities. So your user is loged in but he has no roles (not authorised).
You have to add ROLE_ prefix to role while creating your GrantedAuthority. So you code should look like:
// For xxx
final SimpleGrantedAuthority supervisorAuthority = new SimpleGrantedAuthority(
"ROLE_xxx");
Alternative: You can clear default prefix in RoleVoter but IMO this is not a good choice because ROLE_ prefix actually helps RoleVoter to understand what remaning string is.
<bean id="roleVoter" class="org.springframework.security.vote.RoleVoter">
<property name="rolePrefix" value=""></property>
</bean>

Spring Security Http status 406

I'm working on login with http basic, following this http://howtodoinjava.com/2013/04/16/login-form-based-spring-3-security-example/
and it works well, but some of my page give me http status 406 when I try to load them,I try some answer from similar cases but none of them works(maybe because I just implementing them as close as I can)Any suggestion?
thanks
this is my requestController that still work fine
#Controller
#RequestMapping(value = "/request")
public class RequestController {
#Autowired
private UploadFileService uploadFileService;
#RequestMapping(value = "", method = RequestMethod.GET)
public ModelAndView index() {
return new ModelAndView("page/request-view-table-req");
}
#RequestMapping(value = "/upload", method = RequestMethod.POST)
public String upload(#RequestParam("file") MultipartFile file) {
try {
if (file.getOriginalFilename().endsWith("XLS") || file.getOriginalFilename().endsWith("xls")) {
Excel excel = new Excel(file);
excel.convertToUF();
uploadFileService.add(excel.getListUF());
}
return "redirect:/";
} catch (NullPointerException ex) {
return "redirect:/";
}
}
}
this is templateController that return http status 406
#Controller
#RequestMapping(value = "/template")
public class TemplateController {
#Autowired
private RequestTemplateService requestTemplateService;
#RequestMapping(value = "", method = RequestMethod.GET)
#ResponseBody
public ModelAndView templateView(Model model) {
list_all_template(model);
return new ModelAndView("page/template-add");
}
#RequestMapping(value = "/add", method = RequestMethod.GET)
#ResponseBody
public ModelAndView templateAdd(Model model) {
list_all_template(model);
return new ModelAndView("page/template-add");
}
#RequestMapping(value = "/add/new", method = RequestMethod.POST)
#ResponseBody
public String addTemplate(#ModelAttribute RequestTemplate rt, Model model) {
requestTemplateService.add(rt);
list_all_template(model);
return "redirect:/template";
}
#RequestMapping(value="/delete", method = RequestMethod.GET)
#ResponseBody
public ModelAndView deleteSelected (#RequestParam(value = "nama", required = true) String nama,
Model model)
{
delete_by_nama(nama);
list_all_template(model);
return new ModelAndView("page/template-add");
}
#RequestMapping(value="/update", method = RequestMethod.GET)
#ResponseBody
public ModelAndView updateSelected (#RequestParam(value = "nama", required = true) String nama,
#RequestParam(value = "template") String template,
Model model)
{
requestTemplateService.updateByNama(nama, template);
list_all_template(model);
return new ModelAndView("page/template-view");
}
#RequestMapping(value="/view", method = RequestMethod.GET)
#ResponseBody
public ModelAndView viewSelected (#RequestParam(value = "nama", required = true) String nama,
HttpServletRequest request, HttpServletResponse response, Model model)
{
list_all_template(model);
get_template_by_name(model, nama);
return new ModelAndView("page/template-view");
}
public void delete_by_nama(String nama) {
requestTemplateService.deleteByNama(nama);
}
public void get_template_by_name(Model model, String nama) {
List<RequestTemplate> selectedTemplate = requestTemplateService.getByNama(nama);
model.addAttribute("selectedTemplate", selectedTemplate);
}
public void list_all_template(Model model) {
List<RequestTemplate> RequestTemplates = requestTemplateService.findAll();
model.addAttribute("RequestTemplates", RequestTemplates);
}
}
this is my application-security.xml
<?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.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/login" access="permitAll" />
<intercept-url pattern="/logout" access="permitAll" />
<intercept-url pattern="/accessdenied" access="permitAll" />
<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<form-login login-page="/login" default-target-url="/denied" authentication-failure-url="/accessdenied" />
<logout logout-success-url="/logout" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider>
<user-service>
<user name="lokesh" password="password" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
this is spring-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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<mvc:annotation-driven/>
<mvc:resources mapping="/resources/**" location="/resources/" />
<!-- Scan classpath for annotations (eg: #Service, #Repository etc) -->
<context:component-scan base-package="com.kartuku.somuploader, com.kartuku.somuploader.controller, com.kartuku.somuploader.service, com.kartuku.somuploader.model"/>
<!-- Resolve view name into jsp file located on /WEB-INF -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- MySQL Datasource with Commons DBCP connection pooling -->
<bean class="org.apache.commons.dbcp.BasicDataSource" id="dataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/prosom"/>
<property name="username" value="root"/>
<property name="password" value=""/>
</bean>
<!-- EntityManagerFactory -->
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="persistenceUnitName" value="persistenceUnit"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- Transaction Manager -->
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<!-- another bean -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10000000"/>
</bean>
<!-- Enable #Transactional annotation -->
<tx:annotation-driven/>
</beans>
Try removing #ResponseBody from TemplateController. This may not a Spring Security related issue.

Spring batch integration

I am looking for a guidance/solution with Spring batch integration. I have a directory to which external application will send xml files. My application should read the file content and move the file to another directory.
The application should be able to process the files in parallel.
Thanks in advance.
You can use Spring Integration ftp / sftp combined with Spring Batch:
1.Spring Integration Ftp Configuration :
<bean id="ftpClientFactory"
class="org.springframework.integration.ftp.session.DefaultFtpSessionFactory">
<property name="host" value="${host.name}" />
<property name="port" value="${host.port}" />
<property name="username" value="${host.username}" />
<property name="password" value="${host.password}" />
<property name="bufferSize" value="100000"/>
</bean>
<int:channel id="ftpChannel" />
<int-ftp:outbound-channel-adapter id="ftpOutbound"
channel="ftpChannel" remote-directory="/yourremotedirectory/" session-factory="ftpClientFactory" use-temporary-file-name="false" />
2.Create your reader and autowire a service to provide your items if needed :
#Scope("step")
public class MajorItemReader implements InitializingBean{
private List<YourItem> yourItems= null;
#Autowired
private MyService provider;
public YourItem read() {
if ((yourItems!= null) && (yourItems.size() != 0)) {
return yourItems.remove(0);
}
return null;
}
//Reading Items from Service
private void reloadItems() {
this.yourItems= new ArrayList<YourItem>();
// use the service to provide your Items
if (yourItems.isEmpty()) {
yourItems= null;
}
}
public MyService getProvider() {
return provider;
}
public void setProvider(MyService provider) {
this.provider = provider;
}
#Override
public void afterPropertiesSet() throws Exception {
reloadItems();
}
}
3. Create Your Own Item Processor
public class MyProcessor implements
ItemProcessor<YourItem, YourItem> {
#Override
public YourItem process(YourItem arg0) throws Exception {
// Apply any logic to your Item before transferring it to the writer
return arg0;
}
}
4. Create Your Own Writer :
public class MyWriter{
#Autowired
#Qualifier("ftpChannel")
private MessageChannel messageChannel;
public void write(YourItem pack) throws IOException {
//create your file and from your Item
File file = new File("the_created_file");
// Sending the file via Spring Integration Ftp Channel
Message<File> message = MessageBuilder.withPayload(file).build();
messageChannel.send(message);
}
5.Batch Configuration :
<bean id="dataSourcee"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="" />
<property name="url" value="" />
<property name="username" value="" />
<property name="password" value="" />
</bean>
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
<property name="dataSource" ref="dataSourcee" />
<property name="transactionManager" ref="transactionManagerrr" />
<property name="databaseType" value="" />
</bean>
<bean id="transactionManagerrr"
class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
6.Another ApplicationContext file to Configure Your Job :
<context:annotation-config />
<bean id="provider" class="mypackage.MyService" />
<context:component-scan base-package="mypackage" />
<bean id="myReader" class="mypackage.MyReader"
<property name="provider" ref="provider" />
</bean>
<bean id="myWriter" class="mypackage.MyWriter" />
<bean id="myProcessor" class="mypackage.MyProcessor" />
<bean id="mReader"
class="org.springframework.batch.item.adapter.ItemReaderAdapter">
<property name="targetObject" ref="myReader" />
<property name="targetMethod" value="read" />
</bean>
<bean id="mProcessor"
class="org.springframework.batch.item.adapter.ItemProcessorAdapter">
<property name="targetObject" ref="myProcessor" />
<property name="targetMethod" value="process" />
</bean>
<bean id="mWriter"
class="org.springframework.batch.item.adapter.ItemWriterAdapter">
<property name="targetObject" ref="myWriter" />
<property name="targetMethod" value="write" />
</bean>
<batch:job id="myJob">
<batch:step id="step01">
<batch:tasklet>
<batch:chunk reader="mReader" writer="mWriter"
processor="mProcessor" commit-interval="1">
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="myRunScheduler" class="mypackage.MyJobLauncher" />
<task:scheduled-tasks>
<task:scheduled ref="myJobLauncher" method="run"
cron="0 0/5 * * * ?" />
<!-- this will maker the job runs every 5 minutes -->
</task:scheduled-tasks>
7.Finally Configure A launcher to launch your job :
public class MyJobLauncher {
#Autowired
private JobLauncher jobLauncher;
#Autowired
#Qualifier("myJob")
private Job job;
public void run() {
try {
String dateParam = new Date().toString();
JobParameters param = new JobParametersBuilder().addString("date",
dateParam).toJobParameters();
JobExecution execution = jobLauncher.run(job, param);
execution.stop();
} catch (Exception e) {
e.printStackTrace();
}
}

Spring MVC & Freemarker/Velocity

I've got a problem with Freemarker's and Velocity's view resolver (not running at same moment) - both of them don't see Spring's session beans. Spring's InternalResourceViewResolver works good.
Some code:
<context:component-scan base-package="com.revicostudio.web" />
<mvc:annotation-driven />
<bean id="userSession" class="com.revicostudio.web.session.UserSession" scope="session" />
<bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
<property name="resourceLoaderPath" value="/WEB-INF/jsp/" />
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver">
<property name="cache" value="true" />
<property name="prefix" value="" />
<property name="layoutUrl" value="layout.jsp"/>
<property name="suffix" value=".jsp" />
<property name="exposeSessionAttributes" value="true" />
<property name="exposeRequestAttributes" value="true" />
<property name="requestContextAttribute" value="rc" />
</bean>
In jsp:
${userSession}<br /> <!-- Null if Freemarker's view resolver active, session object if Spring's resolver active -->
${error}<br /> <!-- Normal request attribute, put to map, that works good in both resolvers -->
IndexController:
#Controller
#RequestMapping("/index")
public class IndexController {
#RequestMapping(method=RequestMethod.GET)
public String getIndex(Model model) {
return "index";
}
#ModelAttribute("userRegisterCredentials")
public UserRegisterCredentials getUserRegisterCredentials() {
return new UserRegisterCredentials();
}
#ModelAttribute("userLoginCredentials")
public UserLoginCredentials getUserLoginCredentials() {
return new UserLoginCredentials();
}
}
1.You should annotate controller to point out which model attribute should be exposed in a session
2.In freemarker, access to session attrs is done by a freemarker session wrapper.
Short example below, based on Your code:
#Controller
#SessionAttributes("userRegisterCredentials")
#RequestMapping("/index")
public class IndexController {
#RequestMapping(method=RequestMethod.GET)
public String getIndex(Model model) {
return "index";
}
#ModelAttribute("userRegisterCredentials")
public UserRegisterCredentials getUserRegisterCredentials() {
return new UserRegisterCredentials();
}
}
On the ftl side:${Session.userRegisterCredentials.someStringField}

BadCredentialsException is spring-security

continue my projects I encountered a problem in the authorization for accounts in Spring setsurity
- Problems in the query to the database, all the settings are correct, the database is created at the start of the project, there is no error in debug but at login message pops up in the log:
(UserAuthentication.java:authenticate:56) tradeManager.DAO.Impl.CustomHibernateDaoSupport.find(CustomHibernateDaoSupport.java:60)
tradeManager.service.authentication.UserAuthentication.authenticate(UserAuthentication.java:45)
...
Authentication request failed: org.springframework.security.authentication.BadCredentialsException:
User does not exists!
I added few catches to get precise exception and got new NullPointerException
17:52:34.280:WARN::/tradeManager/j_spring_security_check
java.lang.NullPointerException
at tradeManager.DAO.Impl.CustomHibernateDaoSupport.find(CustomHibernateDaoSupport.java:60)
at tradeManager.service.authentication.UserAuthentication.authenticate(UserAuthentication.java:48)
Can someone explain me what i'm doing wrong? Please help me.
here's the code affected by the query:
#Service("userAuthentication")
public class UserAuthentication implements AuthenticationManager {
protected static Logger userAccessLogger = Logger.getLogger("userAccessLog");
private UserDAO userDAO = new UserDAOImpl();
private Md5PasswordEncoder passwordEncoder = new Md5PasswordEncoder();
public Authentication authenticate(Authentication auth)
throws UsernameNotFoundException {
User user = null;
/*
* Init a database user object
*/
try {
// Retrieve user details from database
//user = userDAO.find(auth.getName());
List<User> list = userDAO.findAllByParam("username", auth.getName());
user = (list.isEmpty()) ? null : list.get(0);
} catch (Exception e) {
StackTraceElement[] stack = e.getStackTrace();
String exception = "";
for (StackTraceElement s : stack) {
exception = exception + s.toString() + "\n\t\t";
}
userAccessLogger.error(exception);
throw new BadCredentialsException("\n\tUser " + auth.getName() + " does not exists!\n");
}
/*
* Compare passwords
* Make sure to encode the password first before comparing
*/
if (user != null) {
if (passwordEncoder.isPasswordValid(user.getPassword(), (String) auth.getCredentials(), null)) {
throw new BadCredentialsException("\n\tWrong password!\n");
}
}
/*
* main logic of authentication manager
* Username and password must be the same to authenticate
*/
if (auth.getName().equals(auth.getCredentials())) {
throw new BadCredentialsException("Entered username and password are the same!");
} else {
assert user != null;
return new UsernamePasswordAuthenticationToken(
auth.getName(),
auth.getCredentials(),
getAuthorities(user.getAccess()));
}
}
/*
* Retrieves the correct ROLE type depending on the access level
*/
public Collection<GrantedAuthority> getAuthorities(Integer access) {
// Create a list of grants for this user
List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>(2);
userAccessLogger.debug("Grant ROLE_USER to this user");
authList.add(new SimpleGrantedAuthority("ROLE_USER"));
if (access.compareTo(1) == 0) {
authList.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
userAccessLogger.debug("Grant ROLE_ADMIN to this user");
}
// Return list of granted authorities
return authList;
}
here is CustomHibernateDaoSupport:
public class CustomHibernateDaoSupport<T> implements DAO<T> {
protected static Logger daoSupportLogger = Logger.getLogger("daoSupportLog");
private Class<T> clazz;
private SessionFactory sessionFactory;
public CustomHibernateDaoSupport(Class<T> clazz) {
this.clazz = clazz;
}
#Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
private SessionFactory getSessionFactory() {
return sessionFactory;
}
#Override
#Transactional
public void save(T entity) {
getSessionFactory().getCurrentSession().save(entity);
}
#Override
#Transactional
public void update(T entity) {
getSessionFactory().getCurrentSession().update(entity);
}
#Override
#Transactional
public void delete(Serializable key) {
Object entity = getSessionFactory().getCurrentSession().get(clazz, key);
if (entity != null) {
getSessionFactory().getCurrentSession().delete(entity);
}
}
#Override
#Transactional
public T find(Serializable key) {
return (T) getSessionFactory().getCurrentSession().get(clazz, key);
}
#Override
#Transactional
public List<T> findAll() {
return getSessionFactory().getCurrentSession().createCriteria(clazz).list();
}
#Override
#Transactional
public List<T> findAllByParam(final String paramName, final Object paramValue) {
return getSessionFactory().getCurrentSession().createCriteria(clazz)
.add(Restrictions.eq(paramName, paramValue))
.list();
}
}
the security settings are like this:
<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:p="http://www.springframework.org/schema/p"
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">
<!-- excluded from Security
<security:http pattern="/resources/*" security="none" />-->
<!-- Configuration of Spring-Security. Set to false to assign custom filters -->
<security:http auto-config="false" use-expressions="true" access-denied-page="/crimea/auth/denied"
entry-point-ref="authenticationEntryPoint" >
<security:logout invalidate-session="true"
logout-success-url="/crimea/auth/login"
delete-cookies="SPRING_SECURITY_REMEMBER_ME_COOKIE"
logout-url="/crimea/auth/logout"/>
<security:intercept-url pattern="/crimea/auth/login" access="permitAll"/>
<security:intercept-url pattern="/crimea/main/admin" access="hasRole('ROLE_ADMIN')"/>
<security:intercept-url pattern="/crimea/main/common" access="hasRole('ROLE_ADMIN','ROLE_USER')"/>
<security:custom-filter ref="authenticationFilter" position="FORM_LOGIN_FILTER"/>
</security:http>
<!-- Custom filter for username and password -->
<bean id="authenticationFilter"
class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"
p:authenticationManager-ref="userAuthentication"
p:authenticationFailureHandler-ref="customAuthenticationFailureHandler"
p:authenticationSuccessHandler-ref="customAuthenticationSuccessHandler"
p:postOnly="false" />
<!-- Custom authentication manager. !!! Username and password must not be the same !!! -->
<bean id="userAuthentication" class="tradeManager.service.authentication.UserAuthentication" />
<!-- default failure URL -->
<bean id="customAuthenticationFailureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"
p:defaultFailureUrl="/crimea/auth/login?error=true" />
<!-- default target URL -->
<bean id="customAuthenticationSuccessHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler"
p:defaultTargetUrl="/crimea/main/common" />
<!-- The AuthenticationEntryPoint -->
<bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"
p:loginFormUrl="/crimea/auth/login" />
<!-- Spring Security autowire the parent property -->
<security:authentication-manager/>
</beans>
I'm not showing User model becouse it standart. Acess is managed by Integer var:
/**
* Access level.
* 1 = Admin role
* 2 = Regular role
*/
#Column(name = "Access", nullable = false)
private Integer access;
Ок, didn't get any helpful answer, so tried my best. First of all, this line got my attention:
<security:intercept-url pattern="/crimea/main/common" access="hasRole('ROLE_ADMIN','ROLE_USER')"
I changed it to:
<security:intercept-url pattern="/crimea/main/common" access="hasRole('ROLE_USER')"
OK, I did more and changed query to username and I writed direct access, from:
list = userDAO.findAllByParam("from username",auth.getName());
to:
list = getSessionFactory().getCurrentSession().createCriteria(User.class)
.add(Restrictions.eq("username", auth.getName())).list();
and added the authentication session attributes to the class and start working He = ((
So, can anyone explain to me why my CustomHibernateDaoSupport class does not work??
OK. I solved my problem ))
First of all? I changed location of #Repository("employeeDAOImpl")annotation.
I changed SQL driver to com.jolbox.bonecp.BoneCPDataSource
naw my datasourse config loks likr this:
<!-- for database, imports the properties from database.properties -->
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="idleConnectionTestPeriod" value="60"/>
<property name="idleMaxAge" value="240"/>
<property name="maxConnectionsPerPartition" value="30"/>
<property name="minConnectionsPerPartition" value="10"/>
<property name="partitionCount" value="3"/>
<property name="acquireIncrement" value="5"/>
<property name="statementsCacheSize" value="100"/>
<property name="releaseHelperThreads" value="3"/>
</bean>
changed Spring shema to:
<tx:annotation-driven transaction-manager="transactionManager"/>
<mvc:annotation-driven />
in UserAuthentication class I added chek for NullPointer
if (entity == null) {
throw new BadCredentialsException("User does not exists!");
}
added to pom.xml maven dep. for new sql driver:
<dependency>
<groupId>com.jolbox</groupId>
<artifactId>bonecp</artifactId>
<version>0.8.0-rc1</version>
</dependency>
So My Authentication is working perfect naw =))
I solved my problem
First, I changed the location of #Repository("employeeDAOImpl")annotation.
I changed SQL driver to com.jolbox.bonecp.BoneCPDataSource
now my datasourse config looks like this:
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="idleConnectionTestPeriod" value="60"/>
<property name="idleMaxAge" value="240"/>
<property name="maxConnectionsPerPartition" value="30"/>
<property name="minConnectionsPerPartition" value="10"/>
<property name="partitionCount" value="3"/>
<property name="acquireIncrement" value="5"/>
<property name="statementsCacheSize" value="100"/>
<property name="releaseHelperThreads" value="3"/>
</bean>
changed Spring schema to:
<tx:annotation-driven transaction-manager="transactionManager"/>
<mvc:annotation-driven />
in UserAuthentication class I added check for a null
if (entity == null) {
throw new BadCredentialsException("User does not exists!");
}
added to pom.xml maven dep. for new sql driver:
com.jolbox
bonecp
0.8.0-rc1
So my authentication is working perfect now =))

Categories