我试图写一个API接口,传入的HTTP请求必须根据数据库中的用户名和密码进行身份验证。这是一种情况,其中2台服务器需要与第三方服务器验证请求,看看它是否有效。场景是这样的:
1.请求服务器通过HTTP POST发送用户会话ID。
1.我的应用程序将会话ID发送到另一个返回用户名的第三方服务器。
1.我的应用程序根据我的数据库检查用户名,并手动设置会话令牌。
1.对我的API的后续请求将需要使用基本身份验证的POST头中的用户名和密码。
我有SecurityConfig:
@EnableWebSecurity
class SecurityConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Configuration
@Order(1)
public class MyAPISecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public MyUserDetailsService myUserDetailsService() {
return new MyUserDetailsService();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.eraseCredentials(false)
.userDetailsService(myUserDetailsService())
.passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
List<String> PATHS_WEB_PERMIT_ALL = new ArrayList<String>();
PATHS_WEB_PERMIT_ALL.add("/rest/myApi/verifyUser");
http.authorizeRequests()
.antMatchers(StringUtils.toStringArray(PATHS_WEB_PERMIT_ALL)).permitAll()
.antMatchers("/rest/myApi/**").authenticated()
.and()
.httpBasic();
http.sessionManagement().maximumSessions(1);
http.csrf().disable();
}
}
}
字符串
我的userDetailsService:
public class MyUserDetailsService implements UserDetailsService {
private static final Logger LOGGER = LoggerFactory.getLogger(MyUserDetailsService.class);
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
LOGGER.info("Finding user: {}", username);
CommUser commUser = commUserService.findByUsernameWithRoles(username);
if (commUser == null) {
LOGGER.error("Unable to find user by username!" + username);
throw new UsernameNotFoundException("User not found!");
} else {
commUser.setAuthorities(createAuthorities(commUser));
return commUser;
}
}
private Set<GrantedAuthority> createAuthorities(CommUser commUser) {
Set<GrantedAuthority> authorities = new LinkedHashSet<>();
List<CommRoleFunctionMode> commRoleFunctionModes = roleFunctionModeRepository.findByCommRoleIn(commUser.getCommRoles());
for (CommRoleFunctionMode commRoleFunctionMode : commRoleFunctionModes) {
authorities.add(new SimpleGrantedAuthority(commRoleFunctionMode.getCommFunction().getFunctionName()));
authorities.add(new SimpleGrantedAuthority(commRoleFunctionMode.getCommFunction().getFunctionName() + commRoleFunctionMode.getCommMode().getModeName()));
}
return authorities;
}
@Autowired
private CommUserService commUserService;
@Autowired
private CommRoleFunctionModeRepository roleFunctionModeRepository;
型
我的RestController:
@RestController
@RequestMapping("/rest/myApi/")
public class MyApiController {
private static final Logger LOGGER = LoggerFactory.getLogger(MyApiController.class);
@PostMapping("verifyUser")
public ResponseEntity verifyUser(@RequestBody @Valid UserKeyDto userKeyDto, HttpServletRequest httpRequest, ProviderManager providerManager) {
if (myApiRestService.myApiLoginValidate(userKeyDto, httpRequest, providerManager)) {
return new ResponseEntity(HttpStatus.OK);
} else {
return new ResponseEntity<>("The username is incorrect!", HttpStatus.UNAUTHORIZED);
}
}
@Autowired
private MyApiRestService myApiRestService;
}
型
和我的MyApiRestService(这是大部分验证发生的地方):
@Service
@CacheConfig(cacheNames = {"myApiRestService"})
public class MyApiRestService {
private static final Logger LOGGER = LoggerFactory.getLogger(MyApiRestService.class);
@Transactional
public boolean myApiLoginValidate(UserKeyDto userKeyDto, HttpServletRequest httpRequest, ProviderManager providerManager) {
String verifyUserUrl = environment.getProperty("api.url") + "/verifyUser";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> request = new HttpEntity<String>(userKeyDto.getSessionId(), headers);
UserKeyDto returnedUserKeyDto = restTemplate.postForObject(verifyUserUrl, request, UserKeyDto.class);
UserDetails userDetails = myUserDetailsService.loadUserByUsername(returnedUserKeyDto.getUsername());
if(userDetails==null) {
return Boolean.FALSE;
}
HttpSession session = httpRequest.getSession(false);
if (session == null) {
session = httpRequest.getSession();
}
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userDetails.getUsername(),
userDetails.getPassword(), userDetails.getAuthorities());
token.setDetails(new WebAuthenticationDetails(httpRequest));
Authentication authenticatedUser = providerManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
// setting role to the session
session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,
SecurityContextHolder.getContext());
return Boolean.TRUE;
}
@Autowired
Environment environment;
@Autowired
MyUserDetailsService myUserDetailsService;
型
UserKeyDto:
public class UserKeyDto {
private static final long serialVersionUID = -2440534315863428792L;
@NotEmpty(message = "SessionId is required!")
private String sessionId;
private String username;
}
型
HTTP请求时出错:
找不到默认的构造函数;嵌套的异常是java. lang. NoSuchMethodException:找不到默认的构造函数;嵌套的构造函数是java.lang.NoSuchMethodException:找不到默认的构造函数;嵌套的构造函数是java. lang.NoSuchMethodException:找不到默认的构造函数。
Controller似乎无法示例化ProviderManager。请帮助。谢谢。
1条答案
按热度按时间kgsdhlau1#
我可以建议一个可能的解决方案,但我不确定:从MyApiController中的控制器方法中删除ProviderManager参数:
字符串
在SecurityConfig类中配置ProviderManager:
型