I'm trying to populate the database with a hashed password and then log in to my application, by matching the data I'm submitting through my log in form, just like how a typical hashed password is suppose to work. I'm using spring security and spring boot, and so far I know that the log in form is working because I get the error Encoded password does not look like BCrypt. And I know that when I'm submitting the user to the database it's not working because I just see a plain string in the password column in the database. I'm really not sure where I'm going wrong here.
Here's my User object
package com.example.objects;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Version;
import com.example.security.PasswordCrypto;
import com.example.security.RoleEnum;
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Version
private Long version;
#Column(name = "username")
private String username;
#Column(name = "password")
private String password;
#Column(name = "email")
private String email;
#Column(name = "termsOfService")
private Boolean termsOfService;
#OneToMany(mappedBy = "user")
private Set<UserRole> roles;
#OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private Set<QuestionAnswerSet> questionAnswerSet;
public static User createUser(String username, String email, String password) {
User user = new User();
user.username = username;
user.email = email;
user.password = PasswordCrypto.getInstance().encrypt(password);
if(user.roles == null) {
user.roles = new HashSet<UserRole>();
}
//create a new user with basic user privileges
user.roles.add(
new UserRole(
RoleEnum.USER.toString(),
user
));
return user;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Boolean getTermsOfService() {
return termsOfService;
}
public void setTermsOfService(Boolean termsOfService) {
this.termsOfService = termsOfService;
}
public Set<QuestionAnswerSet> getQuestionAnswerSet() {
return questionAnswerSet;
}
public void setQuestionAnswerSet(Set<QuestionAnswerSet> questionAnswerSet) {
this.questionAnswerSet = questionAnswerSet;
}
public Set<UserRole> getRoles() {
return roles;
}
public void setRoles(Set<UserRole> roles) {
this.roles = roles;
}
}
Here's my Security Config
package com.example.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private static PasswordEncoder encoder;
#Autowired
private UserDetailsService customUserDetailsService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf()
.csrfTokenRepository(csrfTokenRepository());
http
.authorizeRequests()
.antMatchers("/","/home","/register", "/result").permitAll()
.anyRequest().authenticated();
http
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());
}
#Bean
public PasswordEncoder passwordEncoder() {
if(encoder == null) {
encoder = new BCryptPasswordEncoder();
}
return encoder;
}
private CsrfTokenRepository csrfTokenRepository()
{
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setSessionAttributeName("_csrf");
return repository;
}
}
My user detail service
package com.example.service;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import com.example.dao.UserDao;
import com.example.objects.UserRole;
#Service
#Qualifier("customUserDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
#Autowired
private UserDao userDao;
#Transactional
#Override
public UserDetails loadUserByUsername(final String username)
throws UsernameNotFoundException {
com.example.objects.User user = userDao.findByUsername(username);
List<GrantedAuthority> authorities = buildUserAuthority(user.getRoles());
return buildUserForAuthentication(user, authorities);
}
private User buildUserForAuthentication(com.example.objects.User user,
List<GrantedAuthority> authorities) {
return new User(user.getUsername(), user.getPassword(), authorities);
}
private List<GrantedAuthority> buildUserAuthority(Set<UserRole> userRoles) {
Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();
// Build user's authorities
for (UserRole userRole : userRoles) {
setAuths.add(new SimpleGrantedAuthority(userRole.getRoleName()));
}
return new ArrayList<GrantedAuthority>(setAuths);
}
}
And PasswordCrypto
package com.example.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
public class PasswordCrypto {
#Autowired
private PasswordEncoder passwordEncoder;
private static PasswordCrypto instance;
public static PasswordCrypto getInstance() {
if(instance == null) {
instance = new PasswordCrypto();
}
return instance;
}
public String encrypt(String str) {
return passwordEncoder.encode(str);
}
}
If anyone knows what I'm doing wrong and could help me out, that would be awesome, also let me know if I need to show anymore code. Thanks in advance.
Use encoder to user repository like this :
public class UserRepositoryService implements UserService {
private PasswordEncoder passwordEncoder;
private UserRepository repository;
#Autowired
public UserRepositoryService(PasswordEncoder passwordEncoder,
UserRepository repository) {
this.passwordEncoder = passwordEncoder;
this.repository = repository;
}
private boolean emailExist(String email) {
User user = repository.findByEmail(email);
if (user != null) {
return true;
}
return false;
}
private String encodePassword(RegistrationForm dto) {
String encodedPassword = null;
if (dto.isNormalRegistration()) {
encodedPassword = passwordEncoder.encode(dto.getPassword());
}
return encodedPassword;
}
#Transactional
#Override
public User registerNewUserAccount(RegistrationForm userAccountData)
throws DuplicateEmailException {
if (emailExist(userAccountData.getEmail())) {
LOGGER.debug("Email: {} exists. Throwing exception.",
userAccountData.getEmail());
throw new DuplicateEmailException("The email address: "
+ userAccountData.getEmail() + " is already in use.");
}
String encodedPassword = encodePassword(userAccountData);
User.Builder user = User.getBuilder().email(userAccountData.getEmail())
.firstName(userAccountData.getFirstName())
.lastName(userAccountData.getLastName())
.password(encodedPassword)
.background(userAccountData.getBackground())
.purpose(userAccountData.getPurpose());
if (userAccountData.isSocialSignIn()) {
user.signInProvider(userAccountData.getSignInProvider());
}
User registered = user.build();
return repository.save(registered);
}
}
For morre info, check out this repo
https://bitbucket.org/sulab/biobranch/src/992791aa706d0016de8634ebb6347a81fe952c24/src/main/java/org/scripps/branch/entity/User.java?at=default&fileviewer=file-view-default
My problem was that I needed to add user.setPassword(new BCryptPasswordEncoder().encode(user.getPassword())); in my UserController Post method right before I saved the user
Related
I am working through several tutorials to implement my own security within my project.
The problem is, as configured the system.out.println calls within the class the extends WebSecurityConfigurerAdapter are not being hit. Which means the security class is not being called at all. There are no error messages and I'm also able to navigate to any page within the site without the authorization redirecting to the login page. Also, the login page just does a post and takes me to the home page of the site.
Here is the custom web security configurer adapter:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
ShopmeUserDetailsService shopmeUserDetailsService;
#Bean
public UserDetailsService userDetailsService() {
return new ShopmeUserDetailsService();
}
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
public DaoAuthenticationProvider authenicationProvider() {
System.out.println("In Dao auth security");
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService());
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
System.out.println("In configure security");
//auth.authenticationProvider(authenicationProvider());
//auth.userDetailsService(shopmeUserDetailsService);
auth
.inMemoryAuthentication()
.withUser("user1")
.password(passwordEncoder().encode("user1Pass"))
.roles("USER")
.and()
.withUser("user2")
.password(passwordEncoder().encode("user2Pass"))
.roles("USER")
.and()
.withUser("admin")
.password(passwordEncoder().encode("adminPass"))
.roles("ADMIN");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
System.out.println("In configure security auth");
http
.authorizeRequests()
.anyRequest().authenticated() //all URLs are allowed by any authenticated user, no role restrictions.
.and()
.formLogin() //enable form based authentication
.loginPage("/login") //use a custom login URI
.usernameParameter("email")
.permitAll(true) //login URI can be accessed by anyone
.and()
.logout() //default logout handling
.permitAll(); //allow all as it will be accessed when user is not logged in anymore
}
#Override
public void configure(WebSecurity web) throws Exception{
System.out.println("In configure ignorings");
web.ignoring().antMatchers("/images/**", "/js/**", "/webjars/**" );
}
}
Here is the main app class:
#SpringBootApplication(exclude = { SecurityAutoConfiguration.class })
#EntityScan({"com.shopme.common.entity", "com.shopme.admin.user"})
public class ShopmeBackendApplication {
public static void main(String[] args) {
SpringApplication.run(ShopmeBackendApplication.class, args);
}
}
My main controller:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
#Controller
public class MainController {
#GetMapping("")
public String viewHomePage() {
return "index";
}
#GetMapping("/login")
public String viewLoginPage() {
System.out.println("In viewLoginPage method - MainController");
return "login";
}
#PostMapping("/login")
public String login() {
System.out.println("login attempt");
return "index";
}
}
And finally my other controller for the admin pages:
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import com.shopme.admin.FileUploadUtil;
import com.shopme.common.entity.Role;
import com.shopme.common.entity.User;
#Controller
public class UserController {
#Autowired
private UserService userService;
//private final java.nio.file.Path root = Paths.get("user_photos");
//Updated method to list the first page of users
#GetMapping("/users")
public String listFirstPage(Model model) {
return listUsersByPage(1, model, null);
}
#GetMapping("/users/new")
public String newUser(Model model) throws IOException {
System.out.println("new User method");
List<Role> roles = userService.listRoles();
//System.out.println(multiPartFile.getOriginalFilename());
//String fileName =
StringUtils.cleanPath(multiPartFile.getOriginalFilename());
//String uploadDir = "user_photos";
//FileUploadUtil.saveFile(uploadDir, fileName, multiPartFile);
//Files.copy(multiPartFile.getInputStream(), ((java.nio.file.Path)
this.root).resolve(multiPartFile.getOriginalFilename()));
User user = new User();
user.setEnabled(true);
model.addAttribute("user", user);
model.addAttribute("roles", roles);
model.addAttribute("pageTitle", "Create New User");
return "user_form";
}
#PostMapping("/users/save")
public String saveUser(User user, RedirectAttributes redirect, #RequestParam("image") MultipartFile multiPartFile) throws IOException {
System.out.println(user);
System.out.println(multiPartFile.getOriginalFilename());
String fileName = StringUtils.cleanPath(multiPartFile.getOriginalFilename());
String uploadDir = "user_photos";
FileUploadUtil.saveFile(uploadDir, fileName, multiPartFile);
//Files.copy(multiPartFile.getInputStream(), ((java.nio.file.Path) this.root).resolve(multiPartFile.getOriginalFilename()));
userService.save(user);
redirect.addFlashAttribute("message", "User has been saved successfully!");
return "redirect:/users/page/1?keyword=" + user.getId();
}
#GetMapping("/users/edit/{id}")
public String editUser(#PathVariable(name = "id") Integer id, Model model, RedirectAttributes redirect){
try {
Optional<User> user = userService.getUserById(id);
List<Role> roles = userService.listRoles();
model.addAttribute("user", user);
model.addAttribute("roles", roles);
model.addAttribute("pageTitle", "Edit User (ID: " + id + ")");
return "user_form";
} catch (UserNotFoundException ex) {
redirect.addFlashAttribute("message", ex.getMessage());
return "redirect:/users";
}
}
#GetMapping("users/delete/{id}")
public String deleteUser(#PathVariable(name="id") Integer id, Model model, RedirectAttributes redirect) {
userService.deleteUserById(id);
redirect.addFlashAttribute("message", "User has been deleted successfully!");
return "redirect:/users";
}
#GetMapping("/users/{id}/enabled/{status}")
public String updateUserEnabledStatus(#PathVariable("id") Integer id, #PathVariable("status") boolean enabled, RedirectAttributes redirect) {
userService.updateUserEdabledStatus(id, enabled);
String status = enabled ? "enabled" : "disabled";
String message = "THe user Id " + id + " has been " + status;
redirect.addFlashAttribute("message", message);
return "redirect:/users";
}
#GetMapping("/users/page/{pageNumber}")
public String listUsersByPage(#PathVariable(name = "pageNumber") int pageNumber, Model model, #Param("keyword") String keyword) {
Page<User> page = userService.listByPage(pageNumber, keyword);
List<User> userPagedList = page.getContent();
System.out.println("Pagenumber: " + pageNumber);
System.out.println("Total Elements: " + page.getTotalElements());
System.out.println("Totals Pages: " + page.getTotalPages());
long startCount = (pageNumber - 1) * UserService.USERS_PER_PAGE +1;
long endCount = startCount + UserService.USERS_PER_PAGE -1;
if(endCount > page.getTotalElements()){
endCount = page.getTotalElements();
}
model.addAttribute("totalPages", page.getTotalPages());
model.addAttribute("currentPage", pageNumber);
model.addAttribute("startCount", startCount);
model.addAttribute("endCount", endCount);
model.addAttribute("totalItems", page.getTotalElements());
model.addAttribute("users", userPagedList);
model.addAttribute("keyword", keyword);
return "users";
} //end listUserByPage
#GetMapping("/users/export/csv")
public void exportToCSV(HttpServletResponse response) throws IOException {
List<User> userList = userService.listAll();
UserCsvExporter exporter = new UserCsvExporter();
exporter.export(userList, response);
} //end exportToCsv
#GetMapping("/users/export/excel")
public void exportToExcel(HttpServletResponse response) throws IOException {
List<User> userList = userService.listAll();
UserExcelExporter exporter = new UserExcelExporter();
exporter.export(userList, response);
} //end exportToExcel
#GetMapping("/users/export/pdf")
public void exportToPdf(HttpServletResponse response) throws IOException {
List<User> userList = userService.listAll();
UserPdfExporter exporter = new UserPdfExporter();
exporter.export(userList, response);
} //end exportToPdf
} //end of class
I've spent two days investigating this with no results... any help would greatly be appreciated.
I figured out why this was not working, well at least I have it working with this solution.
I included the WebSecurityConfig.class in the start-up class of the project as shown below:
#SpringBootApplication
#EntityScan({"com.shopme.common.entity", "com.shopme.admin.user"})
public class ShopmeBackendApplication {
public static void main(String[] args) {
SpringApplication.run(new Class[]
{ShopmeBackendApplication.class,
WebSecurityConfig.class}, args);
}
}
I recently wrote a spring boot project that uses spring security oauth2, the auth server is IdentityServer4 for some reason, I can successfully login and get username in my project but I cannot find any way to set user's authority/role.
request.isUserInRole always return false.
#PreAuthorize("hasRole('rolename')") always lead me to 403.
Where can I place some code to set the authorities?
The server has returned some user claims through userinfo endpoint, and my project received them, and I can even see it in the principle param of my controller.
This method always return 403
#ResponseBody
#RequestMapping("admin")
#PreAuthorize("hasRole('admin')")
public String admin(HttpServletRequest request){
return "welcome, you are admin!" + request.isUserInRole("ROLE_admin");
}
application.properties
spring.security.oauth2.client.provider.test.issuer-uri = http://localhost:5000
spring.security.oauth2.client.provider.test.user-name-attribute = name
spring.security.oauth2.client.registration.test.client-id = java
spring.security.oauth2.client.registration.test.client-secret = secret
spring.security.oauth2.client.registration.test.authorization-grant-type = authorization_code
spring.security.oauth2.client.registration.test.scope = openid profile
I print the claims
#ResponseBody
#RequestMapping()
public Object index(Principal user){
OAuth2AuthenticationToken token = (OAuth2AuthenticationToken)user;
return token.getPrincipal().getAttributes();
}
and get the result show there is a claim named 'role'
{"key":"value","role":"admin","preferred_username":"bob"}
Anybody can help me and give me a solution please?
EDIT 1:
The reason is oauth2 client has removed the extracter, and I have to implement the userAuthoritiesMapper.
Finally I got this work by adding the following class:
#Configuration
public class AppConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.oauth2Login().userInfoEndpoint().userAuthoritiesMapper(this.userAuthoritiesMapper());
//.oidcUserService(this.oidcUserService());
super.configure(http);
}
private GrantedAuthoritiesMapper userAuthoritiesMapper() {
return (authorities) -> {
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
authorities.forEach(authority -> {
if (OidcUserAuthority.class.isInstance(authority)) {
OidcUserAuthority oidcUserAuthority = (OidcUserAuthority)authority;
OidcUserInfo userInfo = oidcUserAuthority.getUserInfo();
if (userInfo.containsClaim("role")){
String roleName = "ROLE_" + userInfo.getClaimAsString("role");
mappedAuthorities.add(new SimpleGrantedAuthority(roleName));
}
} else if (OAuth2UserAuthority.class.isInstance(authority)) {
OAuth2UserAuthority oauth2UserAuthority = (OAuth2UserAuthority)authority;
Map<String, Object> userAttributes = oauth2UserAuthority.getAttributes();
if (userAttributes.containsKey("role")){
String roleName = "ROLE_" + (String)userAttributes.get("role");
mappedAuthorities.add(new SimpleGrantedAuthority(roleName));
}
}
});
return mappedAuthorities;
};
}
}
The framework changes so fast and the demos on the web is too old!
I spent a few hours and I find the solution. The problem is with spring oauth security, by default it obtain the user roles from the token using the key 'authorities'. So, I implemented a custom token converter.
The first you need is the custom user token converter, here is the class:
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter;
import org.springframework.util.StringUtils;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
public class CustomUserTokenConverter implements UserAuthenticationConverter {
private Collection<? extends GrantedAuthority> defaultAuthorities;
private UserDetailsService userDetailsService;
private final String AUTHORITIES = "role";
private final String USERNAME = "preferred_username";
private final String USER_IDENTIFIER = "sub";
public CustomUserTokenConverter() {
}
public void setUserDetailsService(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
public void setDefaultAuthorities(String[] defaultAuthorities) {
this.defaultAuthorities = AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils.arrayToCommaDelimitedString(defaultAuthorities));
}
public Map<String, ?> convertUserAuthentication(Authentication authentication) {
Map<String, Object> response = new LinkedHashMap();
response.put(USERNAME, authentication.getName());
if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) {
response.put(AUTHORITIES, AuthorityUtils.authorityListToSet(authentication.getAuthorities()));
}
return response;
}
public Authentication extractAuthentication(Map<String, ?> map) {
if (map.containsKey(USER_IDENTIFIER)) {
Object principal = map.get(USER_IDENTIFIER);
Collection<? extends GrantedAuthority> authorities = this.getAuthorities(map);
if (this.userDetailsService != null) {
UserDetails user = this.userDetailsService.loadUserByUsername((String)map.get(USER_IDENTIFIER));
authorities = user.getAuthorities();
principal = user;
}
return new UsernamePasswordAuthenticationToken(principal, "N/A", authorities);
} else {
return null;
}
}
private Collection<? extends GrantedAuthority> getAuthorities(Map<String, ?> map) {
if (!map.containsKey(AUTHORITIES)) {
return this.defaultAuthorities;
} else {
Object authorities = map.get(AUTHORITIES);
if (authorities instanceof String) {
return AuthorityUtils.commaSeparatedStringToAuthorityList((String)authorities);
} else if (authorities instanceof Collection) {
return AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils.collectionToCommaDelimitedString((Collection)authorities));
} else {
throw new IllegalArgumentException("Authorities must be either a String or a Collection");
}
}
}
}
The you need a custom token converter, here is:
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
import org.springframework.stereotype.Component;
import java.util.Map;
#Component
public class CustomAccessTokenConverter extends DefaultAccessTokenConverter {
#Override
public OAuth2Authentication extractAuthentication(Map<String, ?> claims) {
OAuth2Authentication authentication = super.extractAuthentication(claims);
authentication.setDetails(claims);
return authentication;
}
}
And finally you ResourceServerConfiguration looks like this:
import hello.helper.CustomAccessTokenConverter;
import hello.helper.CustomUserTokenConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
#Configuration
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(final HttpSecurity http) throws Exception {
// #formatter:off
http.authorizeRequests()
.anyRequest().access("hasAnyAuthority('Admin')");
}
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("arawaks");
}
#Bean
#Primary
public RemoteTokenServices tokenServices() {
final RemoteTokenServices tokenServices = new RemoteTokenServices();
tokenServices.setClientId("resourceId");
tokenServices.setClientSecret("resource.secret");
tokenServices.setCheckTokenEndpointUrl("http://localhost:5001/connect/introspect");
tokenServices.setAccessTokenConverter(accessTokenConverter());
return tokenServices;
}
#Bean
public CustomAccessTokenConverter accessTokenConverter() {
final CustomAccessTokenConverter converter = new CustomAccessTokenConverter();
converter.setUserTokenConverter(new CustomUserTokenConverter());
return converter;
}
}
Apparently #wjsgzcn answer (EDIT 1) DOES NOT WORK for reasons below
If you print the attributes returned by the Oauth2UserAuthirty class you will soon notice the contents of the JSON data does not have the role key instead has an authorities key hence you need to use that key to iterate over the list of authorities (roles) to get the actual role name.
Hence the following lines of code will not work as there is no role key in the JSON data returned by the oauth2UserAuthority.getAttributes();
OAuth2UserAuthority oauth2UserAuthority = (OAuth2UserAuthority)authority;
Map<String, Object> userAttributes = oauth2UserAuthority.getAttributes();
if (userAttributes.containsKey("role")){
String roleName = "ROLE_" + (String)userAttributes.get("role");
mappedAuthorities.add(new SimpleGrantedAuthority(roleName));
}
So instead use the following to get the actual role from the getAttributes
if (userAttributes.containsKey("authorities")){
ObjectMapper objectMapper = new ObjectMapper();
ArrayList<Role> authorityList =
objectMapper.convertValue(userAttributes.get("authorities"), new
TypeReference<ArrayList<Role>>() {});
log.info("authList: {}", authorityList);
for(Role role: authorityList){
String roleName = "ROLE_" + role.getAuthority();
log.info("role: {}", roleName);
mappedAuthorities.add(new SimpleGrantedAuthority(roleName));
}
}
Where the Role is a pojo class like so
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Role {
#JsonProperty
private String authority;
}
That way you will be able to get the ROLE_ post prefix which is the actual role granted to the user after successfully authenticated to the Authorization server and the client is returned the LIST of granted authorities (roles).
Now the complete GrantedAuthoritesMapper look like the following:
private GrantedAuthoritiesMapper userAuthoritiesMapper() {
return (authorities) -> {
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
authorities.forEach(authority -> {
if (OidcUserAuthority.class.isInstance(authority)) {
OidcUserAuthority oidcUserAuthority = (OidcUserAuthority)authority;
OidcIdToken idToken = oidcUserAuthority.getIdToken();
OidcUserInfo userInfo = oidcUserAuthority.getUserInfo();
// Map the claims found in idToken and/or userInfo
// to one or more GrantedAuthority's and add it to mappedAuthorities
if (userInfo.containsClaim("authorities")){
ObjectMapper objectMapper = new ObjectMapper();
ArrayList<Role> authorityList = objectMapper.convertValue(userInfo.getClaimAsMap("authorities"), new TypeReference<ArrayList<Role>>() {});
log.info("authList: {}", authorityList);
for(Role role: authorityList){
String roleName = "ROLE_" + role.getAuthority();
log.info("role: {}", roleName);
mappedAuthorities.add(new SimpleGrantedAuthority(roleName));
}
}
} else if (OAuth2UserAuthority.class.isInstance(authority)) {
OAuth2UserAuthority oauth2UserAuthority = (OAuth2UserAuthority)authority;
Map<String, Object> userAttributes = oauth2UserAuthority.getAttributes();
log.info("userAttributes: {}", userAttributes);
// Map the attributes found in userAttributes
// to one or more GrantedAuthority's and add it to mappedAuthorities
if (userAttributes.containsKey("authorities")){
ObjectMapper objectMapper = new ObjectMapper();
ArrayList<Role> authorityList = objectMapper.convertValue(userAttributes.get("authorities"), new TypeReference<ArrayList<Role>>() {});
log.info("authList: {}", authorityList);
for(Role role: authorityList){
String roleName = "ROLE_" + role.getAuthority();
log.info("role: {}", roleName);
mappedAuthorities.add(new SimpleGrantedAuthority(roleName));
}
}
}
});
log.info("The user authorities: {}", mappedAuthorities);
return mappedAuthorities;
};
}
Now you are able to use the userAuthorityMapper in your oauth2Login as follows
#Override
public void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**").authorizeRequests()
.antMatchers("/", "/login**").permitAll()
.antMatchers("/clientPage/**").hasRole("CLIENT")
.anyRequest().authenticated()
.and()
.oauth2Login()
.userInfoEndpoint()
.userAuthoritiesMapper(userAuthoritiesMapper());
}
We have implemented Spring Security in our angular spring boot project.
Here we are getting exception spring security User account is locked
Please review the following code.
SecurityConfiguration.java
package com.jwt.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.csrf.CsrfFilter;
import com.jwt.security.filter.AuthenticationTokenFilter;
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration<jwtAuthenticationEntryPoint> extends WebSecurityConfigurerAdapter{
#Autowired private UserDetailsService userDetailsService;
#Autowired private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint ;
#Autowired
public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.userDetailsService(this.userDetailsService).passwordEncoder( PasswordEncoder());
}
#Bean
public PasswordEncoder PasswordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public AuthenticationTokenFilter authenticationTokenFilterBean( ) {
return new AuthenticationTokenFilter();
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable()
.exceptionHandling()
.authenticationEntryPoint(jwtAuthenticationEntryPoint).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers("/**").permitAll()
.antMatchers("/registration").permitAll()
.antMatchers("/login").permitAll()
.antMatchers(HttpMethod.OPTIONS ,"/**").permitAll()
.anyRequest().authenticated();
httpSecurity.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class)
.addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);
httpSecurity.headers().cacheControl();
httpSecurity.headers().httpStrictTransportSecurity().includeSubDomains(true).maxAgeInSeconds(31536000);
}
}
the authentication token filter AuthenticationTokenFilter.hjava
package com.jwt.security.filter;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;
import com.jwt.security.JwtTokenUtil;
public class AuthenticationTokenFilter extends OncePerRequestFilter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private JwtTokenUtil jwtTokenUtil;
#Value("${jwt.header}")
private String tokenHeader;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// TODO Auto-generated method stub
String authToken = request.getHeader(this.tokenHeader);
if (authToken != null && authToken.length() > 7) {
authToken = authToken.substring(7);
}
String username = jwtTokenUtil.getUsernameFromToken(authToken);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
boolean isValid = jwtTokenUtil.validateToken(authToken, userDetails);
if (isValid) {
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
}
filterChain.doFilter(request, response);
}
}
Here i am getting null for authToken when running from postman
The code for JwtUtil is as following
package com.jwt.security;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
#Component
public class JwtTokenUtil implements Serializable {
static final String CLAIM_KEY_USERNAME = "sub";
static final String CLAIM_KEY_AUDIENCE = "audience";
static final String CLAIM_KEY_CREATED = "created";
#Value("${jwt.secret}")
private String secret;
#Value("${jwt.expiration}")
private Long expiration;
public String getUsernameFromToken(String authToken) {
String username = null;
try {
final Claims claims = getClaimsFromToken(authToken);
username = claims.getSubject();
} catch (Exception e) {
// TODO Auto-generated catch block
username = null;
}
return username;
}
private Claims getClaimsFromToken(String authToken) {
// TODO Auto-generated method stub
Claims claims = null;
try {
claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(authToken).getBody();
} catch (Exception e) {
// TODO Auto-generated catch block
claims = null;
}
return claims;
}
public boolean validateToken(String authToken, UserDetails userDetails) {
// TODO Auto-generated method stub
JwtUser user = (JwtUser) userDetails;
final String username = getUsernameFromToken(authToken);
return (username.equals(user.getUsername()) && !isTokenExpired(authToken));
}
private boolean isTokenExpired(String authToken) {
final Date expiration = getExpirationDateFromToken(authToken);
return expiration.before(new Date());
}
private Date getExpirationDateFromToken(String authToken) {
// TODO Auto-generated method stub
Date expiration = null;
final Claims claims = getClaimsFromToken(authToken);
if (claims != null) {
expiration = claims.getExpiration();
} else {
expiration = null;
}
return expiration;
}
public String generateToken(JwtUser userDetails) {
Map<String,Object> claims = new HashMap<String,Object>();
claims.put(CLAIM_KEY_USERNAME, userDetails.getUsername());
claims.put(CLAIM_KEY_CREATED, new Date());
return generateToken(claims);
}
public String generateToken(Map<String , Object> claims ) {
return Jwts.builder().setClaims(claims).setExpiration(generateExpirationDate()).signWith(SignatureAlgorithm.HS512, secret).compact();
}
private Date generateExpirationDate() {
return new Date(System.currentTimeMillis() + expiration * 1000);
}
}
The code for CsrfHeaderFilter is as following
package com.jwt.security;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.WebUtils;
public class CsrfHeaderFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("...CsrfToken.class.getName() :::" + CsrfToken.class.getName());
// CsrfToken csrfToken = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
// CsrfToken csrfToken = new HttpSessionCsrfTokenRepository().loadToken(request);
CsrfToken csrfToken = (CsrfToken) request.getAttribute("_csrf");
String token = null;
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
if(csrfToken != null) {
token = csrfToken.getToken();
}
if (cookie == null || token != null && !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
filterChain.doFilter(request, response);
}
}
The controller used is AuthenticationController The code is as following
package com.jwt.security.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.jwt.security.JwtTokenUtil;
import com.jwt.security.JwtUser;
import com.jwt.security.domain.User;
import com.jwt.security.domain.UserDTO;
import com.jwt.security.exception.UnauthorizedException;
#RestController
public class AuthenticationController {
#Value("${jwt.header}")
private String tokenHeader;
#Autowired private AuthenticationManager authenticationManager;
#Autowired private JwtTokenUtil jwtTokenUtil;
#PostMapping(value="/login")
public ResponseEntity<UserDTO> login(#RequestBody User user, HttpServletRequest request , HttpServletResponse response) {
try {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
System.out.println("matches ::" + encoder.matches("123", user.getPassword()));
Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword()));
final JwtUser userDetails = (JwtUser)authentication.getPrincipal();
SecurityContextHolder.getContext().setAuthentication(authentication);
final String token = jwtTokenUtil.generateToken(userDetails);
response.setHeader("Token", token);
return new ResponseEntity<UserDTO>(new UserDTO(userDetails.getUser(), token) , HttpStatus.OK);
}catch(UnauthorizedException ex) {
ex.printStackTrace();
throw new UnauthorizedException(ex.getMessage());
}
}
}
On calling http://localhost:8080/login from postman and passing the correct email and password , we are getting the following exception
org.springframework.security.authentication.LockedException: User account is locked
Please advice
The message says "User account is locked". This happens after a number of failed authentication events. The account eventually becomes unlocked depending on implementation.
There are only two places that happens in Spring Security:
AccountStatusUserDetailsChecker.check(UserDetails user)
public void check(UserDetails user) {
if (!user.isAccountNonLocked()) {
throw new LockedException(messages.getMessage(
"AccountStatusUserDetailsChecker.locked", "User account is locked"));
}
if (!user.isEnabled()) {
throw new DisabledException(messages.getMessage(
"AccountStatusUserDetailsChecker.disabled", "User is disabled"));
}
if (!user.isAccountNonExpired()) {
throw new AccountExpiredException(
messages.getMessage("AccountStatusUserDetailsChecker.expired",
"User account has expired"));
}
if (!user.isCredentialsNonExpired()) {
throw new CredentialsExpiredException(messages.getMessage(
"AccountStatusUserDetailsChecker.credentialsExpired",
"User credentials have expired"));
}
}
AbstractUserDetailsAuthenticationProvider.DefaultPreAuthenticationChecks.check(UserDetails user)
So if you want to set a breakpoint, that's where you start.
All of this happens in your UserDetailsService which you have in your configuration.
#Autowired private UserDetailsService userDetailsService;
This service returns an object that implements the UserDetails interface
public interface UserDetails {
boolean isAccountNonLocked();
}
if this method returns false, the account is locked. the name is a bit confusing.
Since we don't know what your UserDetailsService is, we can't tell you how this gets populated. So the recommendation is to just set a break point when the error is thrown.
If you don't want the account locking feature to be enabled, there are different ways to implement that. If you override the UserDetailsService bean you can always return users that are never locked.
Another way is to inject your own checker
DaoAuthenticationProvider daoProvider = ....
daoProvider.setPreAuthenticationChecks(toCheck -> {});
There is also a PostAuthenticationChecks object to see if your password has expired.
I'm writing my own implementation of TokenStore (org.springframework.security.oauth2.provider.token.TokenStore) using MongoDB. There seems to be some problem with converting/mapping of the object in the database back to Java object.
Anyone have a clue how I could solve this?
org.springframework.data.mapping.model.MappingInstantiationException: Failed to instantiate org.springframework.security.authentication.UsernamePasswordAuthenticationToken using constructor NO_CONSTRUCTOR with arguments
at org.springframework.data.convert.ReflectionEntityInstantiator.createInstance(ReflectionEntityInstantiator.java:64) ~[spring-data-commons-1.11.0.RELEASE.jar:na]
at org.springframework.data.convert.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:83) ~[spring-data-commons-1.11.0.RELEASE.jar:na]
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:251) ~[spring-data-mongodb-1.8.0.RELEASE.jar:na]
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:231) ~[spring-data-mongodb-1.8.0.RELEASE.jar:na]
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readValue(MappingMongoConverter.java:1185) ~[spring-data-mongodb-1.8.0.RELEASE.jar:na]
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.access$200(MappingMongoConverter.java:78) ~[spring-data-mongodb-1.8.0.RELEASE.jar:na]
You need to create a converter and register it as Spring Mongo doesn't do this for you.
Create a converter
import com.erranda.abraham.entity.Person;
import com.mongodb.DBObject;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
import java.util.*;
/**
* #version 1.0
* #author: Iain Porter
* #since 23/05/2013
*/
//Hackery to deserialize back into an OAuth2Authentication Object made necessary because Spring Mongo can't map clientAuthentication to authorizationRequest
#ReadingConverter
#SuppressWarnings("rawtypes")
public class OAuth2AuthenticationReadConverter implements Converter<DBObject, OAuth2Authentication> {
#Override
#SuppressWarnings("unchecked")
public OAuth2Authentication convert(DBObject source) {
System.out.println(source);
DBObject storedRequest = (DBObject)source.get("storedRequest");
OAuth2Request oAuth2Request = new OAuth2Request((Map<String, String>)storedRequest.get("requestParameters"),
(String)storedRequest.get("clientId"), null, true, new HashSet((List)storedRequest.get("scope")),
null, null, null, null);
DBObject userAuthorization = (DBObject)source.get("userAuthentication");
Object principal = getPrincipalObject(userAuthorization.get("principal"));
Authentication userAuthentication = new UsernamePasswordAuthenticationToken(principal,
(String)userAuthorization.get("credentials"), getAuthorities((List) userAuthorization.get("authorities")));
OAuth2Authentication authentication = new OAuth2Authentication(oAuth2Request,
userAuthentication );
return authentication;
}
private Object getPrincipalObject(Object principal) {
if(principal instanceof DBObject) {
DBObject principalDBObject = (DBObject)principal;
Person user = new Person (principalDBObject);
return user;
} else {
return principal;
}
}
private Collection<GrantedAuthority> getAuthorities(List<Map<String, String>> authorities) {
Set<GrantedAuthority> grantedAuthorities = new HashSet<GrantedAuthority>(authorities.size());
for(Map<String, String> authority : authorities) {
grantedAuthorities.add(new SimpleGrantedAuthority(authority.get("role")));
}
return grantedAuthorities;
}
}
Then you need to register converter along side your mongodb configuration
import com.erranda.abraham.api.security.OAuth2AuthenticationReadConverter;
import com.mongodb.Mongo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.authentication.UserCredentials;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import org.springframework.data.mongodb.core.convert.CustomConversions;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
#Configuration
public class MongoDbConfiguration extends AbstractMongoConfiguration {
private static final Logger LOG = LoggerFactory.getLogger(MongoDbConfiguration.class);
private static final String MONGO_DB_SERVER = "mongo.db.server";
private static final String MONGO_DB_PORT = "mongo.db.port";
private static final String MONGO_DB_NAME = "mongo.db.name";
private static final String MONGO_DB_LOGON = "mongo.db.logon";
private static final String MONGO_DB_PASSWORD = "mongo.db.password";
private static final String SPRING_PROFILES_ACTIVE = "spring.profiles.active";
#Autowired
private ApplicationContext applicationContext;
#Value("${" + MONGO_DB_SERVER + "}")
private String mongoServer;
#Value("${" + MONGO_DB_PORT + "}")
private int mongoPort;
#Value("${" + MONGO_DB_NAME + "}")
private String mongoDBName;
#Value("${" + MONGO_DB_LOGON + "}")
private String mongoDbLogin;
#Value("${" + MONGO_DB_PASSWORD + "}")
private String mongoDbPassword;
#Override
protected String getDatabaseName() {
return mongoDBName;
}
#Override
#Bean
public Mongo mongo() throws Exception {
return new Mongo(mongoServer, mongoPort);
}
#Override
#Bean
public MongoTemplate mongoTemplate() throws Exception {
if (!StringUtils.isEmpty(mongoDbLogin)) {
LOG.info("Configuring mongoTemplate with credentials.");
MongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongo(), mongoDBName, new UserCredentials(mongoDbLogin, mongoDbPassword));
return new MongoTemplate(mongoDbFactory, mappingMongoConverter());
} else {
LOG.info("Configuring mongoTemplate without credentials.");
MongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongo(), mongoDBName);
return new MongoTemplate(mongoDbFactory, mappingMongoConverter());
}
}
#Override
#Bean
public CustomConversions customConversions() {
List<Converter<?, ?>> converterList = new ArrayList<Converter<?, ?>>();
OAuth2AuthenticationReadConverter converter = new OAuth2AuthenticationReadConverter();
converterList.add(converter);
return new CustomConversions(converterList);
}
private String getContextProperty(final String propertyKey) {
return applicationContext.getEnvironment().getProperty(propertyKey);
}
}
Don't forget to mark as correct if it works for you.
Based on https://github.com/iainporter/oauth2-provider
Hi i need to use mustache with dropwizard, but unable to setup properly.
please have a look...
service.java
public class Service extends Application<ServiceConfiguration>{
public static void main(String[] args) throws Exception {
new Service().run(args);
}
#Override
public void initialize(Bootstrap<ServiceConfiguration> bootstrap) {
bootstrap.addBundle(new ConfiguredAssetsBundle("/assets/", "/","index.html"));
bootstrap.addBundle(new ViewBundle<ServiceConfiguration>());
}
#Override
public void run(ServiceConfiguration config, Environment environment)throws Exception {
environment.jersey().register(new ViewResource());
}
}
ViewResource.java
package resource;
import java.util.LinkedList;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import view_object.UserSample;
import view_object.UsersView;
#Path("/views")
#Produces("text/html;charset=UTF-8")
public class ViewResource {
public ViewResource() {
super();
}
#GET
#Path("/usersample")
public UsersView fetch(){
List<UserSample> users = new LinkedList<UserSample>();
users.add(
new UserSample("user1","user1","Admin", "prit")
);
users.add(
new UserSample("user2","user2","DBA", "deepika")
);
return new UsersView(users);
}
}
UserView.java
package view_object;
import java.util.List;
import io.dropwizard.views.View;
public class UsersView extends View {
private final List<UserSample> users;
public UsersView(List<UserSample> users) {
super("sample.mustache");
this.users = users;
}
public List<UserSample> getUsers() {
return users;
}
}
UserSample.java
package view_object;
public class UserSample {
private String username;
private String password;
private String displayName;
private String displayRole;
public UserSample() {
}
public UserSample(String username, String password, String displayName,
String displayRole) {
this.username = username;
this.password = password;
this.displayName = displayName;
this.displayRole = displayRole;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getDisplayRole() {
return displayRole;
}
public void setDisplayRole(String displayRole) {
this.displayRole = displayRole;
}
}
sample.mustache (Path is "assets/partial/sample.mustache")
<html>
<head>
<title>Users</title>
</head>
<body>
<h1>Users</h1>
{{#users}}
<div>
<p>Username: {{username}}</p>
<p>Displayname: {{displayName}}</p>
</div>
{{/users}}
</body>
</html>
in yaml i have specified
server:
type: simple
applicationContextPath: /
adminContextPath: /admin
rootPath: '/api/*'
connector:
type: http
port: 9000
requestLog:
timeZone: UTC
appenders:
- type: console
threshold: ALL
timeZone: UTC
target: stdout
- type: file
currentLogFilename: ./log/requests.log
threshold: ALL
archive: true
archivedLogFilenamePattern: ./log/requests-%d.log.gz
archivedFileCount: 15
timeZone: UTC
assets:
overrides:
/: src/main/resource/assets/
and also configured ServiceConfiguration.
now my problem is when i hit "http://localhost:9000/api/views/usersample"
it throws "Unable to find a renderer for /view_object/sample.mustache"
please help me out what wrong i am doing here..
I am using dropwizard 0.8.1 and also i have added related dependencies in maven