Feature: server add Ldap user authentication (#1392)

pull/1421/head
Pan_Yujie 1 year ago committed by GitHub
parent 0a08f09e85
commit de703cfca1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -62,5 +62,9 @@
<artifactId>hippo4j-threadpool-server-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-ldap</artifactId>
</dependency>
</dependencies>
</project>

@ -20,6 +20,7 @@ package cn.hippo4j.auth.config;
import cn.hippo4j.auth.constant.Constants;
import cn.hippo4j.auth.filter.JWTAuthenticationFilter;
import cn.hippo4j.auth.filter.JWTAuthorizationFilter;
import cn.hippo4j.auth.filter.LdapAuthenticationFilter;
import cn.hippo4j.auth.security.JwtTokenManager;
import cn.hippo4j.auth.service.impl.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Value;
@ -28,6 +29,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.BeanIds;
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.builders.WebSecurity;
@ -54,9 +56,12 @@ public class GlobalSecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${hippo4j.core.auth.enabled:true}")
private Boolean enableAuthentication;
@Resource
@Resource(name = "userDetailsServiceImpl")
private UserDetailsService userDetailsService;
@Resource(name = "ldapUserDetailsServiceImpl")
private UserDetailsService ldapUserDetailsService;
@Resource
private JwtTokenManager tokenManager;
@ -93,7 +98,9 @@ public class GlobalSecurityConfig extends WebSecurityConfigurerAdapter {
.antMatchers("/static/**", "/index.html", "/favicon.ico", "/avatar.jpg").permitAll()
.antMatchers("/doc.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs").anonymous()
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
// .addFilter(new JWTAuthenticationFilter(authenticationManager())).authenticationProvider(authenticationProvider())
.addFilter(JWTAuthenticationFilter()).authenticationProvider(ldapAuthenticationProvider())
.addFilter(LdapAuthenticationFilter()).authenticationProvider(ldapAuthenticationProvider())
.addFilter(new JWTAuthorizationFilter(tokenManager, authenticationManager()))
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
disableAuthenticationIfNeeded(http);
@ -106,6 +113,20 @@ public class GlobalSecurityConfig extends WebSecurityConfigurerAdapter {
web.ignoring().antMatchers(ignores);
}
private LdapAuthenticationFilter LdapAuthenticationFilter() throws Exception {
LdapAuthenticationFilter filter = new LdapAuthenticationFilter(authenticationManager());
filter.setLdapUserDetailsService(ldapUserDetailsService);
filter.setAuthenticationManager(authenticationManagerBean());
return filter;
}
private JWTAuthenticationFilter JWTAuthenticationFilter() throws Exception {
JWTAuthenticationFilter filter = new JWTAuthenticationFilter(authenticationManager());
filter.setLdapUserDetailsService(userDetailsService);
filter.setAuthenticationManager(authenticationManagerBean());
return filter;
}
/**
* Injection DaoAuthenticationProvider
* Modify hideUserNotFoundExceptions initial value to false
@ -120,6 +141,20 @@ public class GlobalSecurityConfig extends WebSecurityConfigurerAdapter {
return provider;
}
@Bean
public DaoAuthenticationProvider ldapAuthenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(ldapUserDetailsService);
authProvider.setPasswordEncoder(bCryptPasswordEncoder());
return authProvider;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider())
.authenticationProvider(ldapAuthenticationProvider());
}
private void disableAuthenticationIfNeeded(HttpSecurity http) throws Exception {
if (Boolean.FALSE.equals(enableAuthentication)) {
http.authorizeRequests().antMatchers("/hippo4j/v1/cs/**").permitAll();

@ -0,0 +1,72 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.auth.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.LdapContextSource;
import java.util.HashMap;
import java.util.Map;
/**
* Ldap config.
*/
@Configuration
public class LdapConfiguration {
private LdapTemplate ldapTemplate;
@Value("${spring.ldap.urls:}")
private String url;
@Value("${spring.ldap.base:}")
private String base;
@Value("${spring.ldap.embedded.credential.username:}")
private String username;
@Value("${spring.ldap.embedded.credential.password:}")
private String password;
@Bean
public LdapContextSource contextSource() {
LdapContextSource contextSource = new LdapContextSource();
Map<String, Object> config = new HashMap<>(10);
contextSource.setUrl(url);
contextSource.setBase(base);
contextSource.setUserDn(username);
contextSource.setPassword(password);
// fix garbled characters
config.put("java.naming.ldap.attributes.binary", "objectGUID");
contextSource.setPooled(true);
contextSource.setBaseEnvironmentProperties(config);
return contextSource;
}
@Bean
public LdapTemplate ldapTemplate() {
if (null == ldapTemplate) {
ldapTemplate = new LdapTemplate(contextSource());
}
return ldapTemplate;
}
}

@ -25,23 +25,25 @@ import cn.hippo4j.auth.toolkit.ReturnT;
import cn.hippo4j.common.toolkit.JSONUtil;
import cn.hippo4j.server.common.base.Results;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.codec.DecodingException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@ -60,11 +62,18 @@ public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilte
private final ThreadLocal<Integer> rememberMe = new ThreadLocal();
private UserDetailsService userDetailsService;
public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
super.setFilterProcessesUrl(BASE_PATH + "/auth/login");
}
public void setLdapUserDetailsService(UserDetailsService userDetailsServiceImpl) {
this.userDetailsService = userDetailsServiceImpl;
}
@SneakyThrows
@Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
@ -78,8 +87,9 @@ public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilte
request.setAttribute("loginUser", loginUser);
rememberMe.set(loginUser.getRememberMe());
authenticate = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(loginUser.getUsername(), loginUser.getPassword(), new ArrayList()));
UserDetails userDetails = userDetailsService.loadUserByUsername(loginUser.getUsername());
authenticate = new PreAuthenticatedAuthenticationToken(userDetails, null, userDetails.getAuthorities());
} catch (GeneralSecurityException e) {
log.warn("Password decode exception: {}", e.getMessage());
throw new DecodingException(e.getMessage());

@ -0,0 +1,155 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.auth.filter;
import cn.hippo4j.auth.model.biz.user.JwtUser;
import cn.hippo4j.auth.model.biz.user.LoginUser;
import cn.hippo4j.auth.toolkit.AESUtil;
import cn.hippo4j.auth.toolkit.JwtTokenUtil;
import cn.hippo4j.auth.toolkit.ReturnT;
import cn.hippo4j.common.toolkit.JSONUtil;
import cn.hippo4j.server.common.base.Results;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import static cn.hippo4j.auth.constant.Constants.SPLIT_COMMA;
import static cn.hippo4j.common.constant.Constants.BASE_PATH;
import static cn.hippo4j.common.constant.Constants.MAP_INITIAL_CAPACITY;
/**
* Ldap Filter
*/
@Slf4j
public class LdapAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private final ThreadLocal<Integer> rememberMe = new ThreadLocal<>();
private UserDetailsService ldapUserDetailsService;
public void setLdapUserDetailsService(UserDetailsService ldapUserDetailsServiceImpl) {
this.ldapUserDetailsService = ldapUserDetailsServiceImpl;
}
public LdapAuthenticationFilter(AuthenticationManager authenticationManager) {
super.setFilterProcessesUrl(BASE_PATH + "/auth/ldap/login");
}
/**
* Whether it's just the post way
*/
private boolean postOnly = true;
/**
* filter obtains the username and password of LDAP and assembles it on the token.
* Then give the token for authorization
*/
@Override
public Authentication attemptAuthentication(HttpServletRequest request
, HttpServletResponse response) throws AuthenticationException {
if (postOnly && !"POST".equals(request.getMethod())) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
} else {
// Get logged in information from the input stream.
Authentication authenticate = null;
try {
LoginUser loginUser = new ObjectMapper().readValue(request.getInputStream(), LoginUser.class);
String key = new StringBuffer(loginUser.getTag()).reverse().toString();
String password = AESUtil.decrypt(loginUser.getPassword(), key);
loginUser.setPassword(password);
request.setAttribute("loginUser", loginUser);
rememberMe.set(loginUser.getRememberMe());
// ldap validated
UserDetails userDetails = ldapUserDetailsService.loadUserByUsername(loginUser.getUsername());
authenticate = new PreAuthenticatedAuthenticationToken(userDetails, null, userDetails.getAuthorities());
} catch (UsernameNotFoundException e) {
log.debug("User {} not found", e.getMessage());
throw e;
} catch (BadCredentialsException e) {
log.debug("Bad credentials exception: {}", e.getMessage());
throw e;
} catch (Exception e) {
log.debug("Attempt authentication error", e);
}
return authenticate;
}
}
@Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain,
Authentication authResult) throws IOException {
try {
JwtUser jwtUser = (JwtUser) authResult.getPrincipal();
boolean isRemember = rememberMe.get() == 1;
String role = "";
Collection<? extends GrantedAuthority> authorities = jwtUser.getAuthorities();
for (GrantedAuthority authority : authorities) {
role = authority.getAuthority();
}
String token = JwtTokenUtil.createToken(jwtUser.getId(), jwtUser.getUsername(), role, isRemember);
response.setHeader("token", JwtTokenUtil.TOKEN_PREFIX + token);
response.setCharacterEncoding("UTF-8");
Map<String, Object> maps = new HashMap<>(MAP_INITIAL_CAPACITY);
maps.put("data", JwtTokenUtil.TOKEN_PREFIX + token);
maps.put("roles", role.split(SPLIT_COMMA));
response.getWriter().write(JSONUtil.toJSONString(Results.success(maps)));
} finally {
rememberMe.remove();
}
}
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException {
response.setCharacterEncoding("UTF-8");
response.getWriter().write(JSONUtil.toJSONString(new ReturnT<>(ReturnT.JWT_FAIL_CODE, getMessage(failed))));
}
/**
* Return different echo information to the front end according to different exception types
*/
private String getMessage(AuthenticationException failed) {
String message = "Server Error";
if (failed instanceof UsernameNotFoundException) {
message = "用户不存在";
} else if (failed instanceof BadCredentialsException) {
message = "密码错误";
}
return message;
}
}

@ -0,0 +1,39 @@
package cn.hippo4j.auth.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import org.springframework.ldap.odm.annotations.Attribute;
import org.springframework.ldap.odm.annotations.DnAttribute;
import org.springframework.ldap.odm.annotations.Entry;
import org.springframework.ldap.odm.annotations.Id;
import javax.naming.Name;
@Data
@Entry(objectClasses = {"inetOrgPerson", "top"})
public class LdapUserInfo {
@JsonIgnore
@Id
private Name dn;
@Attribute(name = "cn")
@DnAttribute(value = "cn")
private String userName;
@Attribute(name = "sn")
private String lastName;
@Attribute(name = "description")
private String description;
@Attribute(name = "telephoneNumber")
private String telephoneNumber;
@Attribute(name = "userPassword")
private String password;
@Attribute(name = "ou")
private String organizational;
}

@ -0,0 +1,28 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.auth.service;
/**
* Ldap service.
*/
public interface LdapService {
/**
* Login ldap
*/
void login(String username, String password);
}

@ -0,0 +1,72 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.auth.service.impl;
import cn.hippo4j.auth.service.LdapService;
import cn.hippo4j.server.common.base.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.ldap.AuthenticationException;
import org.springframework.ldap.UncategorizedLdapException;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.query.LdapQueryBuilder;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import static org.springframework.ldap.query.LdapQueryBuilder.query;
@Service
@Slf4j
public class LdapServiceImpl implements LdapService {
private final LdapTemplate ldapTemplate;
@Value("${spring.ldap.object-class:}")
private String objectClassName;
@Value("${spring.ldap.account-attribute:}")
private String accountAttribute;
public LdapServiceImpl(LdapTemplate ldapTemplate) {
this.ldapTemplate = ldapTemplate;
}
@Override
public void login(String username, String password) {
try {
ldapTemplate.authenticate(LdapQueryBuilder.query()
.where(accountAttribute).is(username)
.and(query().where("objectClass").is(objectClassName))
, password);
log.debug("{} ldap Login successful", username);
} catch (EmptyResultDataAccessException e) {
throw new UsernameNotFoundException("ldap Can't find the user information ");
} catch (AuthenticationException e) {
log.debug("The user name or account error");
throw new BadCredentialsException("The username or password error");
} catch (UncategorizedLdapException e) {
log.debug("Please check whether the user name password input");
throw new BadCredentialsException("Please check whether the username password input");
} catch (Exception e) {
throw new ServiceException("Abnormal server");
}
}
}

@ -0,0 +1,115 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.auth.service.impl;
import cn.hippo4j.auth.mapper.UserMapper;
import cn.hippo4j.auth.model.UserInfo;
import cn.hippo4j.auth.model.biz.user.JwtUser;
import cn.hippo4j.auth.model.biz.user.LoginUser;
import cn.hippo4j.auth.service.LdapService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.Objects;
import java.util.Set;
/**
* User details service impl.
*/
@Slf4j
@Service
public class LdapUserDetailsServiceImpl implements UserDetailsService {
@Value("${hippo4j.core.auth.enabled:true}")
private Boolean enableAuthentication;
@Resource
private UserMapper userMapper;
@Resource
private LdapService ldapService;
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
JwtUser anonymous = dealWithAnonymous();
if (!Objects.isNull(anonymous)) {
return anonymous;
}
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(requestAttributes)).getRequest();
LoginUser loginUser = (LoginUser) request.getAttribute("loginUser");
// ldap authentication
ldapService.login(userName, loginUser.getPassword());
// By querying the data inventory this user does not exist
UserInfo userInfo = userMapper.selectOne(Wrappers.lambdaQuery(UserInfo.class)
.eq(UserInfo::getUserName, userName)
);
// the database does not, create a ROLE_USER permission to the default user, password is empty
if (Objects.isNull(userInfo)) {
userInfo = new UserInfo();
userInfo.setPassword("");
userInfo.setUserName(loginUser.getUsername());
userInfo.setRole("ROLE_USER");
userMapper.insert(userInfo);
}
// structure jwtUser
JwtUser jwtUser = new JwtUser();
jwtUser.setId(userInfo.getId());
jwtUser.setUsername(userName);
jwtUser.setPassword("");
Set<SimpleGrantedAuthority> authorities = Collections.singleton(new SimpleGrantedAuthority(userInfo.getRole() + ""));
jwtUser.setAuthorities(authorities);
return jwtUser;
}
private JwtUser dealWithAnonymous() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes == null) {
return null;
}
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
LoginUser loginUser = (LoginUser) request.getAttribute("loginUser");
if (Objects.isNull(loginUser)) {
return null;
}
if (Boolean.FALSE.equals(enableAuthentication)) {
JwtUser jwtUser = new JwtUser();
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
jwtUser.setId(1L);
jwtUser.setUsername("anonymous");
jwtUser.setPassword(bCryptPasswordEncoder.encode(loginUser.getPassword()));
Set<SimpleGrantedAuthority> authorities = Collections.singleton(new SimpleGrantedAuthority("ROLE_ADMIN"));
jwtUser.setAuthorities(authorities);
return jwtUser;
}
return null;
}
}

@ -24,11 +24,13 @@ import cn.hippo4j.auth.model.biz.user.LoginUser;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@ -43,6 +45,7 @@ import java.util.Set;
* User details service impl.
*/
@Slf4j
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Value("${hippo4j.core.auth.enabled:true}")
@ -57,10 +60,20 @@ public class UserDetailsServiceImpl implements UserDetailsService {
if (!Objects.isNull(anonymous)) {
return anonymous;
}
UserInfo userInfo = userMapper.selectOne(Wrappers.lambdaQuery(UserInfo.class).eq(UserInfo::getUserName, userName));
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
LoginUser loginUser = (LoginUser) request.getAttribute("loginUser");
String loginPassword = loginUser.getPassword();
UserInfo userInfo = userMapper.selectOne(Wrappers.lambdaQuery(UserInfo.class)
.eq(UserInfo::getUserName, userName)
);
if (Objects.isNull(userInfo)) {
throw new UsernameNotFoundException(userName);
}
// Validation password
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
if (!bCryptPasswordEncoder.matches(loginPassword, userInfo.getPassword())) {
throw new BadCredentialsException(userName + "密码错误,请重新输入");
}
JwtUser jwtUser = new JwtUser();
jwtUser.setId(userInfo.getId());
jwtUser.setUsername(userName);

@ -0,0 +1,20 @@
package cn.hippo4j.auth.toolkit;
import cn.hippo4j.common.toolkit.Assert;
import org.junit.Test;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
public class BCryptPasswordEncoderTest {
@Test
public void bCryptPasswordEncoderTest() {
String password = "12345abc";
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
String encode = bCryptPasswordEncoder.encode(password);
boolean matches = bCryptPasswordEncoder.matches(password, encode);
Assert.isTrue(matches);
}
}

@ -0,0 +1,14 @@
#*************** Ldap Sample Configurations ***************#
### This configuration file does not take effect
### Change the LDAP server information to yourself
### Configure the following configuration file into application.properties
# Ldap Config
spring.ldap.urls=ldap://127.0.0.1:389
spring.ldap.base=dc=xxx,dc=com
spring.ldap.embedded.credential.username=cn=xxxx,dc=xxx,dc=com
spring.ldap.embedded.credential.password=password
# Ldap Entry object-class
spring.ldap.object-class=person
# Ldap account-attribute CommonName ( cn / uid / username / ... )
spring.ldap.account-attribute=cn
Loading…
Cancel
Save