英文:
Multi basic auth with spring security
问题
I want to use basic auth, but I need to use it in UserDetailsService
, not only with the username but also with some information from the header (the header contains the type of user).
This is because I have two users with the same names but different types. For example, I have name:user1 type:USER psw: 1
and name:user1 type:PLAYER psw:1
. So when I log in as the first user, I should search in the database for a user with name=user1
and type=USER
, but UserDetailsService
has only the method loadUserByUsername(String login)
.
So how can I do this?
My UserDetailsService
:
public class UserDetailsService implements org.springframework.security.core.userdetails.UserDetailsService {
private final UserService userService;
@Override
@Transactional
public UserDetails loadUserByUsername(String login) throws UsernameNotFoundException {
return userService.findUserDetailsByLogin(login).orElseThrow(() -> new UsernameNotFoundException(login));
}
}
英文:
I want to use basic auth, but i need use in UserDetailsService
not only username but also some info from header(header contains type of user). <br>
This is bacause I have 2 users with same names but with varios types. For example, I have name:user1 type:USER psw: 1
and name:user1 type:PLAYER psw:1
. So when I login as first user, i should search in db user with name=user1
and type=USER
, but UserDetailsService
has only this method loadUserByUsername(String login)
. <br>
So how can i do this?
My UserDetailsService
:
public class UserDetailsService implements org.springframework.security.core.userdetails.UserDetailsService {
private final UserService userService;
@Override
@Transactional
public UserDetails loadUserByUsername(String login) throws UsernameNotFoundException {
return userService.findUserDetailsByLogin(login).orElseThrow(() -> new UsernameNotFoundException(login));
}
}
答案1
得分: 1
My solution is to use a static context. Using CustomFilter
, I create a context and then use it in the loadUserByUsername
method:
@Component
@RequiredArgsConstructor
public class TypeFilter extends OncePerRequestFilter {
private final TypeService typeService;
private final ObjectMapper mapper;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String uri = request.getRequestURI();
if (!uri.contains("/login") && !uri.contains("/password")) {
chain.doFilter(request, response);
return;
}
String headerValue = request.getHeader(TYPE);
if (StringUtils.isBlank(headerValue)) {
response.setStatus(HttpStatus.BAD_REQUEST.value());
return;
}
try {
Type type = typeService.findByValue(headerValue);
TypeContext.setCurrentType(type);
chain.doFilter(request, response);
} catch (MyException e) {
response.setStatus(HttpStatus.BAD_REQUEST.value());
}
}
}
My config:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(typeFilter, BasicAuthenticationFilter.class);
}
And then I use context in `UserDetailsService`:
```java
public UserDetails loadUserByUsername(String login) throws UsernameNotFoundException {
Type type = TypeContext.getCurrentType();
return userService.findUser(login, type).orElseThrow(() -> new UsernameNotFoundException(login));
}
英文:
My solution is to use a static context. Using CustomFilter
, I create a context and then use it in the loadUserByUsername
method
@Component
@RequiredArgsConstructor
public class TypeFilter extends OncePerRequestFilter {
private final TypeService typeService;
private final ObjectMapper mapper;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String uri = request.getRequestURI();
if (!uri.contains("/login") && !uri.contains("/password")) {
chain.doFilter(request, response);
return;
}
String headerValue = request.getHeader(TYPE);
if (StringUtils.isBlank(headerValue)) {
response.setStatus(HttpStatus.BAD_REQUEST.value());
return;
}
try {
Type type = type Service.findByValue(headerValue);
TypeContext.setCurrentType(type);
chain.doFilter(request, response);
} catch (MyException e) {
response.setStatus(HttpStatus.BAD_REQUEST.value());
}
}
}
My config:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(typeFilter, BasicAuthenticationFilter.class)
And then I use context in UserDeatilsService
:
public UserDetails loadUserByUsername(String login) throws UsernameNotFoundException {
Type type = TypeContext.getCurrentType();
return userService.findUser(login, type).orElseThrow(() -> new UsernameNotFoundException(login));
}
答案2
得分: -1
你可以将loadUserByUsername(String login)
方法包装到另一个方法中。并使用@RequestHeader("YourHeader")
提取你想要的附加信息。
英文:
You could warp the loadUserByUsername(String login)
method into an other method. And extract with @RequestHeader("YourHeader")
the additional Information you want.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论