Updated spring-security-mvc-persisted
Updated spring-security-mvc-persisted - added login error message if unknown user, and switched default H2 database to be embedded in-memory. Added explicit sql creation script to automatically create table on deployment (for some reason the createTableOnStartup flag in the jdbcTokenRepository didn’t work with embedded H2)
This commit is contained in:
parent
7b7b5ae49f
commit
dd020af30a
|
@ -0,0 +1,35 @@
|
||||||
|
package org.baeldung.controller;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Web Controller.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Controller
|
||||||
|
public class MyController {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the view model for the login page (add authentication error
|
||||||
|
* information in the event of an unsuccessful login attempt).
|
||||||
|
*/
|
||||||
|
@RequestMapping(value = "/login", method = RequestMethod.GET)
|
||||||
|
public ModelAndView login(
|
||||||
|
@RequestParam(value = "error", required = false) String error) {
|
||||||
|
|
||||||
|
ModelAndView model = new ModelAndView();
|
||||||
|
if (error != null) {
|
||||||
|
model.addObject("message",
|
||||||
|
"Username or password not recognised - please try again.");
|
||||||
|
}
|
||||||
|
|
||||||
|
model.setViewName("login");
|
||||||
|
return model;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -54,10 +54,10 @@ public class MySimpleUrlAuthenticationSuccessHandler implements AuthenticationSu
|
||||||
boolean isAdmin = false;
|
boolean isAdmin = false;
|
||||||
final Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
|
final Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
|
||||||
for (final GrantedAuthority grantedAuthority : authorities) {
|
for (final GrantedAuthority grantedAuthority : authorities) {
|
||||||
if (grantedAuthority.getAuthority().equals("ROLE_USER")) {
|
if (grantedAuthority.getAuthority().equals(SecurityRole.ROLE_USER.toString())) {
|
||||||
isUser = true;
|
isUser = true;
|
||||||
break;
|
break;
|
||||||
} else if (grantedAuthority.getAuthority().equals("ROLE_ADMIN")) {
|
} else if (grantedAuthority.getAuthority().equals(SecurityRole.ROLE_ADMIN.toString())) {
|
||||||
isAdmin = true;
|
isAdmin = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package org.baeldung.security;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple enum of Security Roles available.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public enum SecurityRole {
|
||||||
|
|
||||||
|
ROLE_USER,
|
||||||
|
ROLE_ADMIN;
|
||||||
|
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.baeldung.security.SecurityRole;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
import org.springframework.security.core.userdetails.User;
|
import org.springframework.security.core.userdetails.User;
|
||||||
|
@ -28,10 +29,8 @@ public class MyUserDetailsService implements UserDetailsService {
|
||||||
|
|
||||||
public MyUserDetailsService() {
|
public MyUserDetailsService() {
|
||||||
|
|
||||||
availableUsers.put("user",
|
populateDemoUsers();
|
||||||
createUser("user", "password", Arrays.asList("ROLE_USER")));
|
|
||||||
availableUsers.put("admin",
|
|
||||||
createUser("admin", "password", Arrays.asList("ROLE_ADMIN")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -49,13 +48,39 @@ public class MyUserDetailsService implements UserDetailsService {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private User createUser(String username, String password, List<String> roles) {
|
/**
|
||||||
|
* Create demo users (note: obviously in a real system these would be persisted
|
||||||
|
* in database or retrieved from another system).
|
||||||
|
*/
|
||||||
|
private void populateDemoUsers(){
|
||||||
|
|
||||||
|
logger.info("Populate demo users");
|
||||||
|
|
||||||
|
availableUsers.put("user",
|
||||||
|
createUser("user", "password", Arrays.asList(SecurityRole.ROLE_USER)));
|
||||||
|
availableUsers.put("admin",
|
||||||
|
createUser("admin", "password", Arrays.asList(SecurityRole.ROLE_ADMIN)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a demo User.
|
||||||
|
*
|
||||||
|
* @param username
|
||||||
|
* Username
|
||||||
|
* @param password
|
||||||
|
* Password
|
||||||
|
* @param roles
|
||||||
|
* Role names user is assigned to
|
||||||
|
* @return User
|
||||||
|
*/
|
||||||
|
private User createUser(String username, String password, List<SecurityRole> roles) {
|
||||||
|
|
||||||
logger.info("Create user " + username);
|
logger.info("Create user " + username);
|
||||||
|
|
||||||
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
|
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
|
||||||
for (String role : roles) {
|
for (SecurityRole role : roles) {
|
||||||
authorities.add(new SimpleGrantedAuthority(role));
|
authorities.add(new SimpleGrantedAuthority(role.toString()));
|
||||||
}
|
}
|
||||||
return new User(username, password, true, true, true, true, authorities);
|
return new User(username, password, true, true, true, true, authorities);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package org.baeldung.spring;
|
package org.baeldung.spring;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.ImportResource;
|
import org.springframework.context.annotation.ImportResource;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
|
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spring Security Configuration.
|
* Spring Security Configuration.
|
||||||
|
@ -13,8 +15,13 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
|
||||||
@ImportResource({ "classpath:webSecurityConfig.xml" })
|
@ImportResource({ "classpath:webSecurityConfig.xml" })
|
||||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthenticationSuccessHandler mySimpleUrlAuthenticationSuccessHandler;
|
||||||
|
|
||||||
public SecurityConfig() {
|
public SecurityConfig() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
-- SQL example for H2 (ran automatically by the spring config for the embedded H2 example)
|
||||||
|
create table if not exists persistent_logins (
|
||||||
|
username varchar_ignorecase(100) not null,
|
||||||
|
series varchar(64) primary key,
|
||||||
|
token varchar(64) not null,
|
||||||
|
last_used timestamp not null
|
||||||
|
);
|
|
@ -1,11 +1,10 @@
|
||||||
# jdbc.X
|
# Jdbc H2 configuration
|
||||||
|
# By default uses the embedded in memory database
|
||||||
|
# Option provided to use the tcp version if you want to start H2 service and view data
|
||||||
|
# Chosen database defined in DatabaseConfig.java
|
||||||
jdbc.driverClassName=org.h2.Driver
|
jdbc.driverClassName=org.h2.Driver
|
||||||
jdbc.url=jdbc:h2:tcp://localhost/~/test
|
#jdbc.url=jdbc:h2:tcp://localhost/~/testDb
|
||||||
|
jdbc.url=jdbc:h2:mem:test;MVCC=TRUE
|
||||||
jdbc.user=sa
|
jdbc.user=sa
|
||||||
jdbc.pass=
|
jdbc.pass=
|
||||||
|
|
||||||
# hibernate.X
|
|
||||||
hibernate.dialect=org.hibernate.dialect.H2Dialect
|
|
||||||
hibernate.show_sql=false
|
|
||||||
hibernate.hbm2ddl.auto=create-drop
|
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
# jdbc.X
|
# Jdbc PostgreSQL option
|
||||||
|
# Chosen database defined in DatabaseConfig.java
|
||||||
jdbc.driverClassName=org.postgresql.Driver
|
jdbc.driverClassName=org.postgresql.Driver
|
||||||
jdbc.url=jdbc:postgresql://localhost:5432
|
jdbc.url=jdbc:postgresql://localhost:5432
|
||||||
|
|
||||||
jdbc.user=postgres
|
jdbc.user=postgres
|
||||||
jdbc.pass=
|
jdbc.pass=
|
||||||
|
|
||||||
# hibernate.X
|
|
||||||
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
|
|
||||||
hibernate.show_sql=false
|
|
||||||
hibernate.hbm2ddl.auto=create-drop
|
|
||||||
|
|
|
@ -5,11 +5,13 @@
|
||||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||||
xmlns:p="http://www.springframework.org/schema/p"
|
xmlns:p="http://www.springframework.org/schema/p"
|
||||||
xmlns:util="http://www.springframework.org/schema/util"
|
xmlns:util="http://www.springframework.org/schema/util"
|
||||||
|
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
|
||||||
xsi:schemaLocation="
|
xsi:schemaLocation="
|
||||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-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-4.0.xsd
|
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
|
||||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.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-3.2.xsd">
|
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
|
||||||
|
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd">
|
||||||
|
|
||||||
|
|
||||||
<http use-expressions="true">
|
<http use-expressions="true">
|
||||||
|
@ -25,28 +27,29 @@
|
||||||
<remember-me data-source-ref="dataSource" token-validity-seconds="86400"/>
|
<remember-me data-source-ref="dataSource" token-validity-seconds="86400"/>
|
||||||
|
|
||||||
</http>
|
</http>
|
||||||
|
|
||||||
|
<!-- create H2 embedded database table on startup -->
|
||||||
|
<jdbc:embedded-database id="dataSource" type="H2">
|
||||||
|
<jdbc:script location="classpath:/persisted_logins_create_table.sql"/>
|
||||||
|
</jdbc:embedded-database>
|
||||||
|
|
||||||
|
<!-- Persistent Remember Me Service -->
|
||||||
|
|
||||||
|
|
||||||
<beans:bean id="rememberMeAuthenticationProvider" class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
|
<beans:bean id="rememberMeAuthenticationProvider" class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
|
||||||
<beans:property name="key" value="myAppKey" />
|
<beans:property name="key" value="myAppKey" />
|
||||||
<beans:property name="tokenRepository" ref="jdbcTokenRepository" />
|
<beans:property name="tokenRepository" ref="jdbcTokenRepository" />
|
||||||
<beans:property name="userDetailsService" ref="myUserDetailsService" />
|
<beans:property name="userDetailsService" ref="myUserDetailsService" />
|
||||||
</beans:bean>
|
</beans:bean>
|
||||||
|
|
||||||
<!-- Uses a database table to maintain a set of persistent login data -->
|
<!-- Uses a database table to maintain a set of persistent login data -->
|
||||||
<beans:bean id="jdbcTokenRepository" class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl">
|
<beans:bean id="jdbcTokenRepository" class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl">
|
||||||
<beans:property name="createTableOnStartup" value="false" />
|
<beans:property name="createTableOnStartup" value="false" />
|
||||||
<beans:property name="dataSource" ref="dataSource" />
|
<beans:property name="dataSource" ref="dataSource" />
|
||||||
</beans:bean>
|
</beans:bean>
|
||||||
|
|
||||||
|
<!-- Authentication Manager (uses same UserDetailsService as RememberMeService)-->
|
||||||
<authentication-manager alias="authenticationManager">
|
<authentication-manager alias="authenticationManager">
|
||||||
<authentication-provider user-service-ref="myUserDetailsService">
|
<authentication-provider user-service-ref="myUserDetailsService">
|
||||||
</authentication-provider>
|
</authentication-provider>
|
||||||
</authentication-manager>
|
</authentication-manager>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</beans:beans>
|
</beans:beans>
|
|
@ -1,5 +1,18 @@
|
||||||
|
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
||||||
<html>
|
<html>
|
||||||
<head></head>
|
<head>
|
||||||
|
<style>
|
||||||
|
.message{
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 10px;
|
||||||
|
color:#FF0000;
|
||||||
|
border: 1px solid;
|
||||||
|
border-radius: 2px;
|
||||||
|
background-color: #F5F6CE;
|
||||||
|
border-color: #FF0000;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<h1>Login</h1>
|
<h1>Login</h1>
|
||||||
|
@ -23,8 +36,17 @@
|
||||||
<td><input name="submit" type="submit" value="submit" /></td>
|
<td><input name="submit" type="submit" value="submit" /></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
<input type="hidden" name="${_csrf.parameterName}"
|
||||||
|
value="${_csrf.token}" />
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
<c:if test="${not empty message}">
|
||||||
|
<div class="message">${message}</div>
|
||||||
|
</c:if>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
Loading…
Reference in New Issue