BAEL-3907: spring-security-web-boot-1 cleanup (#10657)

Co-authored-by: Krzysztof Woyke <krzysztof.woyke.sp@lhsystems.com>
This commit is contained in:
kwoyke 2021-04-23 21:35:22 +02:00 committed by GitHub
parent 09defd1b08
commit 96e97ae79b
47 changed files with 123 additions and 227 deletions

View File

@ -28,12 +28,15 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired @Autowired
private WebApplicationContext applicationContext; private WebApplicationContext applicationContext;
private CustomUserDetailsService userDetailsService;
@Autowired @Autowired
private AuthenticationSuccessHandlerImpl successHandler; private AuthenticationSuccessHandlerImpl successHandler;
@Autowired @Autowired
private DataSource dataSource; private DataSource dataSource;
private CustomUserDetailsService userDetailsService;
@PostConstruct @PostConstruct
public void completeSetup() { public void completeSetup() {
userDetailsService = applicationContext.getBean(CustomUserDetailsService.class); userDetailsService = applicationContext.getBean(CustomUserDetailsService.class);
@ -50,7 +53,7 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
} }
@Override @Override
public void configure(WebSecurity web) throws Exception { public void configure(WebSecurity web) {
web.ignoring() web.ignoring()
.antMatchers("/resources/**"); .antMatchers("/resources/**");
} }

View File

@ -18,13 +18,17 @@ public class AppUser {
private long id; private long id;
private String name; private String name;
@Column(unique = true) @Column(unique = true)
private String username; private String username;
private String password; private String password;
private boolean enabled = true; private boolean enabled = true;
private Date lastLogin; private Date lastLogin;
private AppUser() { public AppUser() {
} }
public AppUser(String name, String email, String password) { public AppUser(String name, String email, String password) {

View File

@ -15,15 +15,27 @@ import javax.persistence.Table;
@Entity @Entity
@Table(name = "Tweet") @Table(name = "Tweet")
public class Tweet { public class Tweet {
@Id @Id
@GeneratedValue(strategy = GenerationType.SEQUENCE) @GeneratedValue(strategy = GenerationType.SEQUENCE)
private long id; private long id;
private String tweet; private String tweet;
private String owner; private String owner;
@ElementCollection(targetClass = String.class, fetch = FetchType.EAGER) @ElementCollection(targetClass = String.class, fetch = FetchType.EAGER)
@CollectionTable(name = "Tweet_Likes") @CollectionTable(name = "Tweet_Likes")
private Set<String> likes = new HashSet<>(); private Set<String> likes = new HashSet<>();
public Tweet() {
}
public Tweet(String tweet, String owner) {
this.tweet = tweet;
this.owner = owner;
}
public long getId() { public long getId() {
return id; return id;
} }
@ -32,14 +44,6 @@ public class Tweet {
this.id = id; this.id = id;
} }
private Tweet() {
}
public Tweet(String tweet, String owner) {
this.tweet = tweet;
this.owner = owner;
}
public String getTweet() { public String getTweet() {
return tweet; return tweet;
} }
@ -63,5 +67,4 @@ public class Tweet {
public void setLikes(Set<String> likes) { public void setLikes(Set<String> likes) {
this.likes = likes; this.likes = likes;
} }
} }

View File

@ -9,6 +9,6 @@ import com.baeldung.relationships.models.Tweet;
public interface TweetRepository extends PagingAndSortingRepository<Tweet, Long> { public interface TweetRepository extends PagingAndSortingRepository<Tweet, Long> {
@Query("select twt from Tweet twt JOIN twt.likes as lk where lk = ?#{ principal?.username } or twt.owner = ?#{ principal?.username }") @Query("SELECT twt FROM Tweet twt JOIN twt.likes AS lk WHERE lk = ?#{ principal?.username } OR twt.owner = ?#{ principal?.username }")
Page<Tweet> getMyTweetsAndTheOnesILiked(Pageable pageable); Page<Tweet> getMyTweetsAndTheOnesILiked(Pageable pageable);
} }

View File

@ -12,6 +12,7 @@ import org.springframework.transaction.annotation.Transactional;
import com.baeldung.relationships.models.AppUser; import com.baeldung.relationships.models.AppUser;
public interface UserRepository extends CrudRepository<AppUser, Long> { public interface UserRepository extends CrudRepository<AppUser, Long> {
AppUser findByUsername(String username); AppUser findByUsername(String username);
List<AppUser> findByName(String name); List<AppUser> findByName(String name);
@ -19,5 +20,5 @@ public interface UserRepository extends CrudRepository<AppUser, Long> {
@Query("UPDATE AppUser u SET u.lastLogin=:lastLogin WHERE u.username = ?#{ principal?.username }") @Query("UPDATE AppUser u SET u.lastLogin=:lastLogin WHERE u.username = ?#{ principal?.username }")
@Modifying @Modifying
@Transactional @Transactional
public void updateLastLogin(@Param("lastLogin") Date lastLogin); void updateLastLogin(@Param("lastLogin") Date lastLogin);
} }

View File

@ -2,7 +2,6 @@ package com.baeldung.relationships.security;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List;
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;
@ -14,14 +13,10 @@ public class AppUserPrincipal implements UserDetails {
private final AppUser user; private final AppUser user;
//
public AppUserPrincipal(AppUser user) { public AppUserPrincipal(AppUser user) {
this.user = user; this.user = user;
} }
//
@Override @Override
public String getUsername() { public String getUsername() {
return user.getUsername(); return user.getUsername();
@ -34,8 +29,7 @@ public class AppUserPrincipal implements UserDetails {
@Override @Override
public Collection<? extends GrantedAuthority> getAuthorities() { public Collection<? extends GrantedAuthority> getAuthorities() {
final List<GrantedAuthority> authorities = Collections.singletonList(new SimpleGrantedAuthority("User")); return Collections.<GrantedAuthority>singletonList(new SimpleGrantedAuthority("User"));
return authorities;
} }
@Override @Override
@ -58,10 +52,7 @@ public class AppUserPrincipal implements UserDetails {
return true; return true;
} }
//
public AppUser getAppUser() { public AppUser getAppUser() {
return user; return user;
} }
} }

View File

@ -1,9 +1,7 @@
package com.baeldung.relationships.security; package com.baeldung.relationships.security;
import java.io.IOException;
import java.util.Date; import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -21,7 +19,7 @@ public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHa
private UserRepository userRepository; private UserRepository userRepository;
@Override @Override
public void onAuthenticationSuccess(HttpServletRequest arg0, HttpServletResponse arg1, Authentication arg2) throws IOException, ServletException { public void onAuthenticationSuccess(HttpServletRequest arg0, HttpServletResponse arg1, Authentication arg2) {
userRepository.updateLastLogin(new Date()); userRepository.updateLastLogin(new Date());
} }

View File

@ -17,11 +17,8 @@ public class CustomUserDetailsService implements UserDetailsService {
@Autowired @Autowired
private WebApplicationContext applicationContext; private WebApplicationContext applicationContext;
private UserRepository userRepository;
public CustomUserDetailsService() { private UserRepository userRepository;
super();
}
@PostConstruct @PostConstruct
public void completeSetup() { public void completeSetup() {
@ -36,5 +33,4 @@ public class CustomUserDetailsService implements UserDetailsService {
} }
return new AppUserPrincipal(appUser); return new AppUserPrincipal(appUser);
} }
} }

View File

@ -15,7 +15,7 @@ import com.baeldung.relationships.models.Tweet;
public class DummyContentUtil { public class DummyContentUtil {
public static final List<AppUser> generateDummyUsers() { public static List<AppUser> generateDummyUsers() {
List<AppUser> appUsers = new ArrayList<>(); List<AppUser> appUsers = new ArrayList<>();
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
appUsers.add(new AppUser("Lionel Messi", "lionel@messi.com", passwordEncoder.encode("li1234"))); appUsers.add(new AppUser("Lionel Messi", "lionel@messi.com", passwordEncoder.encode("li1234")));
@ -31,7 +31,7 @@ public class DummyContentUtil {
return appUsers; return appUsers;
} }
public static final List<Tweet> generateDummyTweets(List<AppUser> users) { public static List<Tweet> generateDummyTweets(List<AppUser> users) {
List<Tweet> tweets = new ArrayList<>(); List<Tweet> tweets = new ArrayList<>();
Random random = new Random(); Random random = new Random();
IntStream.range(0, 9) IntStream.range(0, 9)
@ -59,5 +59,4 @@ public class DummyContentUtil {
grantedAuthorities.add(grantedAuthority); grantedAuthorities.add(grantedAuthority);
return grantedAuthorities; return grantedAuthorities;
} }
} }

View File

@ -3,11 +3,9 @@ package com.baeldung.roles.custom;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.PropertySource; import org.springframework.context.annotation.PropertySource;
@SpringBootApplication @SpringBootApplication
@ComponentScan("com.baeldung.roles.custom")
@PropertySource("classpath:application-defaults.properties") @PropertySource("classpath:application-defaults.properties")
public class Application extends SpringBootServletInitializer { public class Application extends SpringBootServletInitializer {
public static void main(String[] args) { public static void main(String[] args) {

View File

@ -13,11 +13,6 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@EnableWebMvc @EnableWebMvc
public class MvcConfig implements WebMvcConfigurer { public class MvcConfig implements WebMvcConfigurer {
public MvcConfig() {
super();
}
//
@Bean @Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer(); return new PropertySourcesPlaceholderConfigurer();

View File

@ -17,6 +17,7 @@ import org.springframework.stereotype.Component;
@Component @Component
public class SetupData { public class SetupData {
@Autowired @Autowired
private UserRepository userRepository; private UserRepository userRepository;
@ -39,18 +40,18 @@ public class SetupData {
private void initUsers() { private void initUsers() {
final Privilege privilege1 = privilegeRepository.findByName("FOO_READ_PRIVILEGE"); final Privilege privilege1 = privilegeRepository.findByName("FOO_READ_PRIVILEGE");
final Privilege privilege2 = privilegeRepository.findByName("FOO_WRITE_PRIVILEGE"); final Privilege privilege2 = privilegeRepository.findByName("FOO_WRITE_PRIVILEGE");
//
final User user1 = new User(); final User user1 = new User();
user1.setUsername("john"); user1.setUsername("john");
user1.setPassword(encoder.encode("123")); user1.setPassword(encoder.encode("123"));
user1.setPrivileges(new HashSet<Privilege>(Arrays.asList(privilege1))); user1.setPrivileges(new HashSet<>(Arrays.asList(privilege1)));
user1.setOrganization(organizationRepository.findByName("FirstOrg")); user1.setOrganization(organizationRepository.findByName("FirstOrg"));
userRepository.save(user1); userRepository.save(user1);
//
final User user2 = new User(); final User user2 = new User();
user2.setUsername("tom"); user2.setUsername("tom");
user2.setPassword(encoder.encode("111")); user2.setPassword(encoder.encode("111"));
user2.setPrivileges(new HashSet<Privilege>(Arrays.asList(privilege1, privilege2))); user2.setPrivileges(new HashSet<>(Arrays.asList(privilege1, privilege2)));
user2.setOrganization(organizationRepository.findByName("SecondOrg")); user2.setOrganization(organizationRepository.findByName("SecondOrg"));
userRepository.save(user2); userRepository.save(user2);
} }
@ -58,7 +59,7 @@ public class SetupData {
private void initOrganizations() { private void initOrganizations() {
final Organization org1 = new Organization("FirstOrg"); final Organization org1 = new Organization("FirstOrg");
organizationRepository.save(org1); organizationRepository.save(org1);
//
final Organization org2 = new Organization("SecondOrg"); final Organization org2 = new Organization("SecondOrg");
organizationRepository.save(org2); organizationRepository.save(org2);
} }
@ -66,7 +67,7 @@ public class SetupData {
private void initPrivileges() { private void initPrivileges() {
final Privilege privilege1 = new Privilege("FOO_READ_PRIVILEGE"); final Privilege privilege1 = new Privilege("FOO_READ_PRIVILEGE");
privilegeRepository.save(privilege1); privilegeRepository.save(privilege1);
//
final Privilege privilege2 = new Privilege("FOO_WRITE_PRIVILEGE"); final Privilege privilege2 = new Privilege("FOO_WRITE_PRIVILEGE");
privilegeRepository.save(privilege2); privilegeRepository.save(privilege2);
} }

View File

@ -5,6 +5,5 @@ import org.springframework.data.jpa.repository.JpaRepository;
public interface OrganizationRepository extends JpaRepository<Organization, Long> { public interface OrganizationRepository extends JpaRepository<Organization, Long> {
public Organization findByName(String name); Organization findByName(String name);
} }

View File

@ -5,6 +5,5 @@ import org.springframework.data.jpa.repository.JpaRepository;
public interface PrivilegeRepository extends JpaRepository<Privilege, Long> { public interface PrivilegeRepository extends JpaRepository<Privilege, Long> {
public Privilege findByName(String name); Privilege findByName(String name);
} }

View File

@ -10,5 +10,4 @@ public interface UserRepository extends JpaRepository<User, Long> {
@Transactional @Transactional
void removeUserByUsername(String username); void removeUserByUsername(String username);
} }

View File

@ -8,6 +8,7 @@ import javax.persistence.Id;
@Entity @Entity
public class Foo { public class Foo {
@Id @Id
@GeneratedValue(strategy = GenerationType.AUTO) @GeneratedValue(strategy = GenerationType.AUTO)
private Long id; private Long id;
@ -15,19 +16,13 @@ public class Foo {
@Column(nullable = false) @Column(nullable = false)
private String name; private String name;
//
public Foo() { public Foo() {
super();
} }
public Foo(String name) { public Foo(String name) {
super();
this.name = name; this.name = name;
} }
//
public Long getId() { public Long getId() {
return id; return id;
} }
@ -44,8 +39,6 @@ public class Foo {
this.name = name; this.name = name;
} }
//
@Override @Override
public String toString() { public String toString() {
final StringBuilder builder = new StringBuilder(); final StringBuilder builder = new StringBuilder();

View File

@ -16,19 +16,13 @@ public class Organization {
@Column(nullable = false, unique = true) @Column(nullable = false, unique = true)
private String name; private String name;
//
public Organization() { public Organization() {
super();
} }
public Organization(String name) { public Organization(String name) {
super();
this.name = name; this.name = name;
} }
//
public Long getId() { public Long getId() {
return id; return id;
} }
@ -45,8 +39,6 @@ public class Organization {
this.name = name; this.name = name;
} }
//
@Override @Override
public String toString() { public String toString() {
final StringBuilder builder = new StringBuilder(); final StringBuilder builder = new StringBuilder();

View File

@ -16,19 +16,13 @@ public class Privilege {
@Column(nullable = false, unique = true) @Column(nullable = false, unique = true)
private String name; private String name;
//
public Privilege() { public Privilege() {
super();
} }
public Privilege(String name) { public Privilege(String name) {
super();
this.name = name; this.name = name;
} }
//
public Long getId() { public Long getId() {
return id; return id;
} }
@ -45,8 +39,6 @@ public class Privilege {
this.name = name; this.name = name;
} }
//
@Override @Override
public String toString() { public String toString() {
final StringBuilder builder = new StringBuilder(); final StringBuilder builder = new StringBuilder();

View File

@ -35,13 +35,6 @@ public class User {
@JoinColumn(name = "organization_id", referencedColumnName = "id") @JoinColumn(name = "organization_id", referencedColumnName = "id")
private Organization organization; private Organization organization;
//
public User() {
super();
}
//
public Long getId() { public Long getId() {
return id; return id;
} }
@ -82,8 +75,6 @@ public class User {
this.organization = organization; this.organization = organization;
} }
//
@Override @Override
public String toString() { public String toString() {
final StringBuilder builder = new StringBuilder(); final StringBuilder builder = new StringBuilder();

View File

@ -14,14 +14,11 @@ public class CustomMethodSecurityExpressionRoot extends SecurityExpressionRoot i
super(authentication); super(authentication);
} }
//
public boolean isMember(Long OrganizationId) { public boolean isMember(Long OrganizationId) {
final User user = ((MyUserPrincipal) this.getPrincipal()).getUser(); final User user = ((MyUserPrincipal) this.getPrincipal()).getUser();
return user.getOrganization().getId().longValue() == OrganizationId.longValue(); return user.getOrganization().getId().longValue() == OrganizationId.longValue();
} }
//
@Override @Override
public Object getFilterObject() { public Object getFilterObject() {
return this.filterObject; return this.filterObject;
@ -46,5 +43,4 @@ public class CustomMethodSecurityExpressionRoot extends SecurityExpressionRoot i
public void setReturnObject(Object obj) { public void setReturnObject(Object obj) {
this.returnObject = obj; this.returnObject = obj;
} }
} }

View File

@ -27,11 +27,8 @@ public class CustomPermissionEvaluator implements PermissionEvaluator {
private boolean hasPrivilege(Authentication auth, String targetType, String permission) { private boolean hasPrivilege(Authentication auth, String targetType, String permission) {
for (final GrantedAuthority grantedAuth : auth.getAuthorities()) { for (final GrantedAuthority grantedAuth : auth.getAuthorities()) {
System.out.println("here " + grantedAuth); if (grantedAuth.getAuthority().startsWith(targetType) && grantedAuth.getAuthority().contains(permission)) {
if (grantedAuth.getAuthority().startsWith(targetType)) { return true;
if (grantedAuth.getAuthority().contains(permission)) {
return true;
}
} }
} }
return false; return false;

View File

@ -15,6 +15,7 @@ import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.authority.AuthorityUtils;
public class MySecurityExpressionRoot implements MethodSecurityExpressionOperations { public class MySecurityExpressionRoot implements MethodSecurityExpressionOperations {
protected final Authentication authentication; protected final Authentication authentication;
private AuthenticationTrustResolver trustResolver; private AuthenticationTrustResolver trustResolver;
private RoleHierarchy roleHierarchy; private RoleHierarchy roleHierarchy;
@ -30,8 +31,6 @@ public class MySecurityExpressionRoot implements MethodSecurityExpressionOperati
public final String delete = "delete"; public final String delete = "delete";
public final String admin = "administration"; public final String admin = "administration";
//
private Object filterObject; private Object filterObject;
private Object returnObject; private Object returnObject;
@ -47,14 +46,11 @@ public class MySecurityExpressionRoot implements MethodSecurityExpressionOperati
throw new RuntimeException("method hasAuthority() not allowed"); throw new RuntimeException("method hasAuthority() not allowed");
} }
//
public boolean isMember(Long OrganizationId) { public boolean isMember(Long OrganizationId) {
final User user = ((MyUserPrincipal) this.getPrincipal()).getUser(); final User user = ((MyUserPrincipal) this.getPrincipal()).getUser();
return user.getOrganization().getId().longValue() == OrganizationId.longValue(); return user.getOrganization().getId().longValue() == OrganizationId.longValue();
} }
//
@Override @Override
public final boolean hasAnyAuthority(String... authorities) { public final boolean hasAnyAuthority(String... authorities) {
return hasAnyAuthorityName(null, authorities); return hasAnyAuthorityName(null, authorities);
@ -136,7 +132,6 @@ public class MySecurityExpressionRoot implements MethodSecurityExpressionOperati
private Set<String> getAuthoritySet() { private Set<String> getAuthoritySet() {
if (roles == null) { if (roles == null) {
roles = new HashSet<String>();
Collection<? extends GrantedAuthority> userAuthorities = authentication.getAuthorities(); Collection<? extends GrantedAuthority> userAuthorities = authentication.getAuthorities();
if (roleHierarchy != null) { if (roleHierarchy != null) {

View File

@ -14,12 +14,6 @@ public class MyUserDetailsService implements UserDetailsService {
@Autowired @Autowired
private UserRepository userRepository; private UserRepository userRepository;
public MyUserDetailsService() {
super();
}
// API
@Override @Override
public UserDetails loadUserByUsername(final String username) { public UserDetails loadUserByUsername(final String username) {
final User user = userRepository.findByUsername(username); final User user = userRepository.findByUsername(username);

View File

@ -16,14 +16,10 @@ public class MyUserPrincipal implements UserDetails {
private final User user; private final User user;
//
public MyUserPrincipal(User user) { public MyUserPrincipal(User user) {
this.user = user; this.user = user;
} }
//
@Override @Override
public String getUsername() { public String getUsername() {
return user.getUsername(); return user.getUsername();
@ -36,7 +32,7 @@ public class MyUserPrincipal implements UserDetails {
@Override @Override
public Collection<? extends GrantedAuthority> getAuthorities() { public Collection<? extends GrantedAuthority> getAuthorities() {
final List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); final List<GrantedAuthority> authorities = new ArrayList<>();
for (final Privilege privilege : user.getPrivileges()) { for (final Privilege privilege : user.getPrivileges()) {
authorities.add(new SimpleGrantedAuthority(privilege.getName())); authorities.add(new SimpleGrantedAuthority(privilege.getName()));
} }
@ -63,10 +59,7 @@ public class MyUserPrincipal implements UserDetails {
return true; return true;
} }
//
public User getUser() { public User getUser() {
return user; return user;
} }
} }

View File

@ -39,8 +39,6 @@ public class MainController {
return foo; return foo;
} }
//
@PreAuthorize("hasAuthority('FOO_READ_PRIVILEGE')") @PreAuthorize("hasAuthority('FOO_READ_PRIVILEGE')")
@GetMapping("/foos") @GetMapping("/foos")
@ResponseBody @ResponseBody
@ -48,8 +46,6 @@ public class MainController {
return new Foo(name); return new Foo(name);
} }
//
@PreAuthorize("isMember(#id)") @PreAuthorize("isMember(#id)")
@GetMapping("/organizations/{id}") @GetMapping("/organizations/{id}")
@ResponseBody @ResponseBody
@ -64,5 +60,4 @@ public class MainController {
public MyUserPrincipal retrieveUserDetails(@AuthenticationPrincipal MyUserPrincipal principal) { public MyUserPrincipal retrieveUserDetails(@AuthenticationPrincipal MyUserPrincipal principal) {
return principal; return principal;
} }
} }

View File

@ -3,11 +3,9 @@ package com.baeldung.roles.ip;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.PropertySource; import org.springframework.context.annotation.PropertySource;
@SpringBootApplication @SpringBootApplication
@ComponentScan("com.baeldung.ip")
@PropertySource("classpath:application-defaults.properties") @PropertySource("classpath:application-defaults.properties")
public class IpApplication extends SpringBootServletInitializer { public class IpApplication extends SpringBootServletInitializer {
public static void main(String[] args) { public static void main(String[] args) {

View File

@ -1,10 +1,5 @@
package com.baeldung.roles.ip.config; package com.baeldung.roles.ip.config;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@ -15,13 +10,17 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.web.authentication.WebAuthenticationDetails; import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Component @Component
public class CustomIpAuthenticationProvider implements AuthenticationProvider { public class CustomIpAuthenticationProvider implements AuthenticationProvider {
Set<String> whitelist = new HashSet<String>(); Set<String> whitelist = new HashSet<>();
public CustomIpAuthenticationProvider() { public CustomIpAuthenticationProvider() {
super();
whitelist.add("11.11.11.11"); whitelist.add("11.11.11.11");
whitelist.add("127.0.0.1"); whitelist.add("127.0.0.1");
} }
@ -30,18 +29,17 @@ public class CustomIpAuthenticationProvider implements AuthenticationProvider {
public Authentication authenticate(Authentication auth) throws AuthenticationException { public Authentication authenticate(Authentication auth) throws AuthenticationException {
WebAuthenticationDetails details = (WebAuthenticationDetails) auth.getDetails(); WebAuthenticationDetails details = (WebAuthenticationDetails) auth.getDetails();
String userIp = details.getRemoteAddress(); String userIp = details.getRemoteAddress();
if(! whitelist.contains(userIp)){ if (!whitelist.contains(userIp)) {
throw new BadCredentialsException("Invalid IP Address"); throw new BadCredentialsException("Invalid IP Address");
} }
final String name = auth.getName(); final String name = auth.getName();
final String password = auth.getCredentials().toString(); final String password = auth.getCredentials().toString();
if (name.equals("john") && password.equals("123")) { if (name.equals("john") && password.equals("123")) {
List<GrantedAuthority> authorities =new ArrayList<GrantedAuthority>(); List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("ROLE_USER")); authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
return new UsernamePasswordAuthenticationToken(name, password, authorities); return new UsernamePasswordAuthenticationToken(name, password, authorities);
} } else {
else{
throw new BadCredentialsException("Invalid username or password"); throw new BadCredentialsException("Invalid username or password");
} }
} }

View File

@ -8,7 +8,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration @Configuration
@EnableWebSecurity//(debug = true) @EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter { public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired @Autowired
@ -22,7 +22,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override @Override
protected void configure(final HttpSecurity http) throws Exception { protected void configure(final HttpSecurity http) throws Exception {
// @formatter:off
http.authorizeRequests() http.authorizeRequests()
.antMatchers("/login").permitAll() .antMatchers("/login").permitAll()
// .antMatchers("/foos/**").hasIpAddress("11.11.11.11") // .antMatchers("/foos/**").hasIpAddress("11.11.11.11")
@ -30,7 +29,5 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
.anyRequest().authenticated() .anyRequest().authenticated()
.and().formLogin().permitAll() .and().formLogin().permitAll()
.and().csrf().disable(); .and().csrf().disable();
// @formatter:on
} }
} }

View File

@ -11,9 +11,8 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.web.FilterChainProxy; import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.SecurityFilterChain;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
@Controller @Controller
@ -23,7 +22,7 @@ public class MainController {
@Qualifier("springSecurityFilterChain") @Qualifier("springSecurityFilterChain")
private Filter springSecurityFilterChain; private Filter springSecurityFilterChain;
@RequestMapping(method = RequestMethod.GET, value = "/filters") @GetMapping("/filters")
@ResponseBody @ResponseBody
public void getFilters() { public void getFilters() {
FilterChainProxy filterChainProxy = (FilterChainProxy) springSecurityFilterChain; FilterChainProxy filterChainProxy = (FilterChainProxy) springSecurityFilterChain;
@ -32,11 +31,10 @@ public class MainController {
.flatMap(chain -> chain.getFilters().stream()) .flatMap(chain -> chain.getFilters().stream())
.forEach(filter -> System.out.println(filter.getClass())); .forEach(filter -> System.out.println(filter.getClass()));
} }
@RequestMapping(method = RequestMethod.GET, value = "/foos/{id}") @GetMapping("/foos/{id}")
@ResponseBody @ResponseBody
public Foo findById(@PathVariable final long id, HttpServletRequest request) { public Foo findById(@PathVariable final long id, HttpServletRequest request) {
return new Foo("Sample"); return new Foo("Sample");
} }
} }

View File

@ -12,11 +12,11 @@ import org.springframework.security.core.userdetails.UserDetailsService;
public class CustomAuthenticationProvider extends DaoAuthenticationProvider { public class CustomAuthenticationProvider extends DaoAuthenticationProvider {
private final UserRepository userRepository; private final UserRepository userRepository;
@SuppressWarnings("unused") @SuppressWarnings("unused")
private UserDetailsService userDetailsService; private UserDetailsService userDetailsService;
public CustomAuthenticationProvider(UserRepository userRepository, UserDetailsService userDetailsService){ public CustomAuthenticationProvider(UserRepository userRepository, UserDetailsService userDetailsService){
super();
this.setUserDetailsService(userDetailsService); this.setUserDetailsService(userDetailsService);
this.userRepository = userRepository; this.userRepository = userRepository;
} }

View File

@ -2,7 +2,6 @@ package com.baeldung.roles.rolesauthorities;
import java.io.IOException; import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
@ -15,7 +14,7 @@ import org.springframework.stereotype.Component;
public class MyLogoutSuccessHandler implements LogoutSuccessHandler { public class MyLogoutSuccessHandler implements LogoutSuccessHandler {
@Override @Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
final HttpSession session = request.getSession(); final HttpSession session = request.getSession();
if (session != null) { if (session != null) {
session.removeAttribute("user"); session.removeAttribute("user");

View File

@ -24,12 +24,6 @@ public class MyUserDetailsService implements UserDetailsService {
@Autowired @Autowired
private UserRepository userRepository; private UserRepository userRepository;
public MyUserDetailsService() {
super();
}
// API
@Override @Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
@ -38,17 +32,20 @@ public class MyUserDetailsService implements UserDetailsService {
if (user == null) { if (user == null) {
throw new UsernameNotFoundException("No user found with username: " + email); throw new UsernameNotFoundException("No user found with username: " + email);
} }
org.springframework.security.core.userdetails.User userDetails = new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(), user.isEnabled(), true, true, true, getAuthorities(user.getRoles())); return new org.springframework.security.core.userdetails.User(user.getEmail(),
return userDetails; user.getPassword(),
user.isEnabled(),
true,
true,
true,
getAuthorities(user.getRoles()));
} catch (final Exception e) { } catch (final Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
// UTIL private Collection<? extends GrantedAuthority> getAuthorities(Collection<Role> roles) {
List<GrantedAuthority> authorities = new ArrayList<>();
private final Collection<? extends GrantedAuthority> getAuthorities(Collection<Role> roles) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for (Role role: roles) { for (Role role: roles) {
authorities.add(new SimpleGrantedAuthority(role.getName())); authorities.add(new SimpleGrantedAuthority(role.getName()));
authorities.addAll(role.getPrivileges() authorities.addAll(role.getPrivileges()

View File

@ -8,7 +8,7 @@ import org.springframework.context.annotation.Configuration;
@Configuration @Configuration
@EnableAutoConfiguration @EnableAutoConfiguration
@ComponentScan("com.baeldung.rolesauthorities") @ComponentScan("com.baeldung.roles.rolesauthorities")
public class RolesAuthoritiesApplication extends SpringBootServletInitializer { public class RolesAuthoritiesApplication extends SpringBootServletInitializer {
public static void main(String[] args) { public static void main(String[] args) {
System.setProperty("spring.profiles.default", "rolesauthorities"); System.setProperty("spring.profiles.default", "rolesauthorities");

View File

@ -13,11 +13,6 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@EnableWebMvc @EnableWebMvc
public class MvcConfig implements WebMvcConfigurer { public class MvcConfig implements WebMvcConfigurer {
public MvcConfig() {
super();
}
//
@Bean @Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer(); return new PropertySourcesPlaceholderConfigurer();

View File

@ -31,10 +31,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired @Autowired
private LogoutSuccessHandler myLogoutSuccessHandler; private LogoutSuccessHandler myLogoutSuccessHandler;
public SecurityConfig() {
super();
}
@Override @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception { protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider()); auth.authenticationProvider(authProvider());
@ -50,7 +46,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override @Override
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http http
.csrf().disable() .csrf().disable()
.authorizeRequests() .authorizeRequests()
@ -69,11 +64,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
.logoutSuccessUrl("/logout.html?logSucc=true") .logoutSuccessUrl("/logout.html?logSucc=true")
.deleteCookies("JSESSIONID") .deleteCookies("JSESSIONID")
.permitAll(); .permitAll();
// @formatter:on
} }
// beans
@Bean @Bean
public DaoAuthenticationProvider authProvider() { public DaoAuthenticationProvider authProvider() {
final CustomAuthenticationProvider authProvider final CustomAuthenticationProvider authProvider
@ -86,5 +78,4 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
public PasswordEncoder encoder() { public PasswordEncoder encoder() {
return new BCryptPasswordEncoder(11); return new BCryptPasswordEncoder(11);
} }
} }

View File

@ -21,16 +21,12 @@ public class Privilege {
private Collection<Role> roles; private Collection<Role> roles;
public Privilege() { public Privilege() {
super();
} }
public Privilege(String name) { public Privilege(String name) {
super();
this.name = name; this.name = name;
} }
//
public Long getId() { public Long getId() {
return id; return id;
} }

View File

@ -27,16 +27,12 @@ public class Role {
private String name; private String name;
public Role() { public Role() {
super();
} }
public Role(String name) { public Role(String name) {
super();
this.name = name; this.name = name;
} }
//
public Long getId() { public Long getId() {
return id; return id;
} }

View File

@ -35,14 +35,11 @@ public class User {
private boolean isUsing2FA; private boolean isUsing2FA;
//
@ManyToMany(fetch = FetchType.EAGER) @ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")) @JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
private Collection<Role> roles; private Collection<Role> roles;
public User() { public User() {
super();
this.enabled = false; this.enabled = false;
} }
@ -143,5 +140,4 @@ public class User {
.append(firstName).append(", lastName=").append(lastName).append(", email=").append(email).append(", password=").append(password).append(", enabled=").append(enabled).append(", roles=").append(roles).append("]"); .append(firstName).append(", lastName=").append(lastName).append(", email=").append(email).append(", password=").append(password).append(", enabled=").append(enabled).append(", roles=").append(roles).append("]");
return builder.toString(); return builder.toString();
} }
} }

View File

@ -74,7 +74,7 @@ public class SetupDataLoader implements ApplicationListener<ContextRefreshedEven
} }
@Transactional @Transactional
private Privilege createPrivilegeIfNotFound(String name) { public Privilege createPrivilegeIfNotFound(String name) {
Privilege privilege = privilegeRepository.findByName(name); Privilege privilege = privilegeRepository.findByName(name);
if (privilege == null) { if (privilege == null) {
privilege = new Privilege(name); privilege = new Privilege(name);
@ -84,7 +84,7 @@ public class SetupDataLoader implements ApplicationListener<ContextRefreshedEven
} }
@Transactional @Transactional
private Role createRoleIfNotFound(String name, Collection<Privilege> privileges) { public Role createRoleIfNotFound(String name, Collection<Privilege> privileges) {
Role role = roleRepository.findByName(name); Role role = roleRepository.findByName(name);
if (role == null) { if (role == null) {
role = new Role(name); role = new Role(name);
@ -93,5 +93,4 @@ public class SetupDataLoader implements ApplicationListener<ContextRefreshedEven
} }
return role; return role;
} }
} }

View File

@ -9,6 +9,7 @@ import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
public class MinuteBasedVoter implements AccessDecisionVoter { public class MinuteBasedVoter implements AccessDecisionVoter {
@Override @Override
public boolean supports(ConfigAttribute attribute) { public boolean supports(ConfigAttribute attribute) {
return true; return true;
@ -21,6 +22,12 @@ public class MinuteBasedVoter implements AccessDecisionVoter {
@Override @Override
public int vote(Authentication authentication, Object object, Collection collection) { public int vote(Authentication authentication, Object object, Collection collection) {
return authentication.getAuthorities().stream().map(GrantedAuthority::getAuthority).filter(r -> "ROLE_USER".equals(r) && LocalDateTime.now().getMinute() % 2 != 0).findAny().map(s -> ACCESS_DENIED).orElseGet(() -> ACCESS_ABSTAIN); return authentication.getAuthorities()
.stream()
.map(GrantedAuthority::getAuthority)
.filter(r -> "ROLE_USER".equals(r) && LocalDateTime.now().getMinute() % 2 != 0)
.findAny()
.map(s -> ACCESS_DENIED)
.orElse(ACCESS_ABSTAIN);
} }
} }

View File

@ -4,10 +4,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Created by ambrusadrianz on 30/09/2016.
*/
@Configuration @Configuration
public class VoterMvcConfig implements WebMvcConfigurer { public class VoterMvcConfig implements WebMvcConfigurer {
@Override @Override

View File

@ -22,28 +22,46 @@ import java.util.List;
@Configuration @Configuration
@EnableWebSecurity @EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired @Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// @formatter: off auth
auth.inMemoryAuthentication().withUser("user").password(passwordEncoder().encode("pass")).roles("USER").and().withUser("admin").password(passwordEncoder().encode("pass")).roles("ADMIN"); .inMemoryAuthentication()
// @formatter: on .withUser("user")
.password(passwordEncoder().encode("pass"))
.roles("USER")
.and()
.withUser("admin")
.password(passwordEncoder().encode("pass"))
.roles("ADMIN");
} }
@Override @Override
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
// @formatter: off
http http
// needed so our login could work .csrf()
.csrf().disable().authorizeRequests().anyRequest().authenticated().accessDecisionManager(accessDecisionManager()).and().formLogin().permitAll().and().logout().permitAll() .disable()
.deleteCookies("JSESSIONID").logoutSuccessUrl("/login"); .authorizeRequests()
// @formatter: on .anyRequest()
.authenticated()
.accessDecisionManager(accessDecisionManager())
.and()
.formLogin()
.permitAll()
.and()
.logout()
.permitAll()
.deleteCookies("JSESSIONID").logoutSuccessUrl("/login");
} }
@Bean @Bean
public AccessDecisionManager accessDecisionManager() { public AccessDecisionManager accessDecisionManager() {
// @formatter: off List<AccessDecisionVoter<?>> decisionVoters = Arrays.asList(
List<AccessDecisionVoter<? extends Object>> decisionVoters = Arrays.asList(new WebExpressionVoter(), new RoleVoter(), new AuthenticatedVoter(), new MinuteBasedVoter()); new WebExpressionVoter(),
// @formatter: on new RoleVoter(),
new AuthenticatedVoter(),
new MinuteBasedVoter());
return new UnanimousBased(decisionVoters); return new UnanimousBased(decisionVoters);
} }

View File

@ -1,12 +1,6 @@
package com.baeldung.roles.voter; package com.baeldung.roles.voter;
/**
* Created by ambrusadrianz on 09/10/2016.
*/
// @Configuration // @Configuration
// @ImportResource({ "classpath:spring-security-custom-voter.xml" }) // @ImportResource({ "classpath:spring-security-custom-voter.xml" })
public class XmlSecurityConfig { public class XmlSecurityConfig {
public XmlSecurityConfig() {
super();
}
} }

View File

@ -36,12 +36,15 @@ import static org.springframework.util.Assert.isTrue;
@ContextConfiguration @ContextConfiguration
@DirtiesContext @DirtiesContext
public class SpringDataWithSecurityIntegrationTest { public class SpringDataWithSecurityIntegrationTest {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
@Autowired
private ServletContext servletContext;
private static UserRepository userRepository; private static UserRepository userRepository;
private static TweetRepository tweetRepository; private static TweetRepository tweetRepository;
@Autowired
private ServletContext servletContext;
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
@Before @Before
public void testInit() { public void testInit() {
ctx.register(AppConfig.class); ctx.register(AppConfig.class);

View File

@ -13,7 +13,7 @@ import io.restassured.specification.RequestSpecification;
import org.junit.Test; import org.junit.Test;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
// In order to execute these tests, com.baeldung.custom.Application needs to be running. // In order to execute these tests, com.baeldung.roles.custom.Application needs to be running.
public class ApplicationLiveTest { public class ApplicationLiveTest {
@Test @Test
@ -36,8 +36,6 @@ public class ApplicationLiveTest {
assertTrue(response.asString().contains("id")); assertTrue(response.asString().contains("id"));
} }
//
@Test @Test
public void givenUserMemberInOrganization_whenGetOrganization_thenOK() { public void givenUserMemberInOrganization_whenGetOrganization_thenOK() {
final Response response = givenAuth("john", "123").get("http://localhost:8082/organizations/1"); final Response response = givenAuth("john", "123").get("http://localhost:8082/organizations/1");
@ -51,8 +49,6 @@ public class ApplicationLiveTest {
assertEquals(403, response.getStatusCode()); assertEquals(403, response.getStatusCode());
} }
//
@Test @Test
public void givenDisabledSecurityExpression_whenGetFooByName_thenError() { public void givenDisabledSecurityExpression_whenGetFooByName_thenError() {
final Response response = givenAuth("john", "123").get("http://localhost:8082/foos?name=sample"); final Response response = givenAuth("john", "123").get("http://localhost:8082/foos?name=sample");
@ -60,7 +56,6 @@ public class ApplicationLiveTest {
assertTrue(response.asString().contains("method hasAuthority() not allowed")); assertTrue(response.asString().contains("method hasAuthority() not allowed"));
} }
//
private RequestSpecification givenAuth(String username, String password) { private RequestSpecification givenAuth(String username, String password) {
return RestAssured.given().log().uri().auth().form(username, password, new FormAuthConfig("/login","username","password")); return RestAssured.given().log().uri().auth().form(username, password, new FormAuthConfig("/login","username","password"));
} }

View File

@ -9,7 +9,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import org.apache.http.HttpHeaders; import org.apache.http.HttpHeaders;
import com.baeldung.roles.custom.Application; import com.baeldung.roles.custom.Application;
import com.baeldung.roles.custom.persistence.model.Foo; import com.baeldung.roles.custom.persistence.model.Foo;
import org.junit.jupiter.api.Test; import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
@ -82,8 +82,7 @@ public class CustomUserDetailsServiceIntegrationTest {
private static String asJsonString(final Object obj) throws Exception { private static String asJsonString(final Object obj) throws Exception {
final ObjectMapper mapper = new ObjectMapper(); final ObjectMapper mapper = new ObjectMapper();
final String jsonContent = mapper.writeValueAsString(obj); return mapper.writeValueAsString(obj);
return jsonContent;
} }
} }

View File

@ -8,7 +8,7 @@ import io.restassured.response.Response;
import org.junit.Test; import org.junit.Test;
// In order to execute these tests, com.baeldung.ip.IpApplication needs to be running. // In order to execute these tests, com.baeldung.roles.ip.IpApplication needs to be running.
public class IpLiveTest { public class IpLiveTest {
@Test @Test