带有附加自定义参数的 Spring Boot 身份验证
Springboot authentication with an additional custom parameter
我正在尝试在我的应用程序中使用 spring 启动安全。我需要同时访问销售人员和客户。每个都映射到不同的实体,进而使用不同的存储库。
我的 UserDetailServive 实现如何根据自定义表单参数使用不同的存储库?
<form th:action="@{/login}" method="post">
<div>
<label>User Name: <input type="text" name="username"/></label>
<label>Password: <input type="password" name="password"/></label>
<label>User type: <input type="radio" name="userType" value="customer"/>
<input type="radio" name="userType" value="salesMen"/></label>
</div>
<div><input type="submit" value="Login"/></div>
</form>
@Service
public class UserDetailServiceImpl implements UserDetailsService {
@Autowired
SalesMenRepository salesMenRepository;
@Autowired
CustomersRepository customersRepository;
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
// How can I get userType parameter ????
if ("salesMen".equals(userType)) {
Optional<SalesMan> salesMan = salesMenRepository.findById(userName);
if (!salesMan.isPresent()) {
throw new UsernameNotFoundException(userName);
}
return new UserDetailsImp(salesMan.get());
} else {
Optional<Customer> customer = customersRepository.findById(userName);
if (!customer.isPresent()) {
throw new UsernameNotFoundException(userName);
}
return new UserDetailsImp(customer.get());
}
}
}
您可以用任何字符连接 userName
和 userType
,例如冒号:
userName:userType
,在loadUserByUsername方法中,你拆分得到
String[] parts = userName.split(":");
但是,当您将自定义参数加入用户名时,您必须自定义身份验证过滤器。在我的例子中,我添加了名称为 dmBhxhId
的新自定义参数。我创建 CustomUser:
public class CustomUser extends User {
private Long dmBhxhId;
public Long getDmBhxhId() {
return dmBhxhId;
}
public void setDmBhxhId(Long dmBhxhId) {
this.dmBhxhId = dmBhxhId;
}
public CustomUser(String username, String password, Collection<? extends GrantedAuthority> authorities,
Long dmBhxhId) {
super(username, password, authorities);
this.dmBhxhId = dmBhxhId;
}
public CustomUser(String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
}
}
我自定义身份验证过滤器
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private String extraParameter = "extra";
private String delimiter = ":";
/**
* Given an {@link HttpServletRequest}, this method extracts the username
* and the extra input values and returns a combined username string of
* those values separated by the delimiter string.
*
* @param request
* The {@link HttpServletRequest} containing the HTTP request
* variables from which the username client domain values can be
* extracted
*/
@Override
protected String obtainUsername(HttpServletRequest request) {
String username = request.getParameter(getUsernameParameter());
String extraInput = request.getParameter(getExtraParameter());
Map<String, String[]> map = request.getParameterMap();
String combinedUsername = username + getDelimiter() + extraInput;
return combinedUsername;
}
/**
* @return The parameter name which will be used to obtain the extra input
* from the login request
*/
public String getExtraParameter() {
return this.extraParameter;
}
/**
* @param extraParameter
* The parameter name which will be used to obtain the extra
* input from the login request
*/
public void setExtraParameter(String extraParameter) {
this.extraParameter = extraParameter;
}
/**
* @return The delimiter string used to separate the username and extra
* input values in the string returned by
* <code>obtainUsername()</code>
*/
public String getDelimiter() {
return this.delimiter;
}
/**
* @param delimiter
* The delimiter string used to separate the username and extra
* input values in the string returned by
* <code>obtainUsername()</code>
*/
public void setDelimiter(String delimiter) {
this.delimiter = delimiter;
}
}
在 SecurityConfiguration 文件中,我初始化了 CustomAuthenticationFilter
@Bean
public CustomAuthenticationFilter customAuthenticationFilter() throws Exception {
CustomAuthenticationFilter bcsAuthFilter = new CustomAuthenticationFilter();
bcsAuthFilter.setAuthenticationManager(authenticationManager());
bcsAuthFilter.setAuthenticationFailureHandler(ajaxAuthenticationFailureHandler);
bcsAuthFilter.setAuthenticationSuccessHandler(ajaxAuthenticationSuccessHandler);
bcsAuthFilter.setFilterProcessesUrl("/api/authentication");
bcsAuthFilter.setPostOnly(true);
bcsAuthFilter.setExtraParameter("dm_bhxh_id");
bcsAuthFilter.setUsernameParameter("j_username");
bcsAuthFilter.setPasswordParameter("j_password");
return bcsAuthFilter;
}
并在配置方法中调用
.addFilterBefore(bcsAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
看起来像
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.ignoringAntMatchers("/websocket/**").ignoringAntMatchers("/api/public/odts/**")
.and()
.addFilterBefore(bcsAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.addFilterAfter(new CsrfCookieGeneratorFilter(), CsrfFilter.class)
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
....
完成,希望对您有所帮助!
对不起,我的英文不好。
我正在尝试在我的应用程序中使用 spring 启动安全。我需要同时访问销售人员和客户。每个都映射到不同的实体,进而使用不同的存储库。
我的 UserDetailServive 实现如何根据自定义表单参数使用不同的存储库?
<form th:action="@{/login}" method="post">
<div>
<label>User Name: <input type="text" name="username"/></label>
<label>Password: <input type="password" name="password"/></label>
<label>User type: <input type="radio" name="userType" value="customer"/>
<input type="radio" name="userType" value="salesMen"/></label>
</div>
<div><input type="submit" value="Login"/></div>
</form>
@Service
public class UserDetailServiceImpl implements UserDetailsService {
@Autowired
SalesMenRepository salesMenRepository;
@Autowired
CustomersRepository customersRepository;
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
// How can I get userType parameter ????
if ("salesMen".equals(userType)) {
Optional<SalesMan> salesMan = salesMenRepository.findById(userName);
if (!salesMan.isPresent()) {
throw new UsernameNotFoundException(userName);
}
return new UserDetailsImp(salesMan.get());
} else {
Optional<Customer> customer = customersRepository.findById(userName);
if (!customer.isPresent()) {
throw new UsernameNotFoundException(userName);
}
return new UserDetailsImp(customer.get());
}
}
}
您可以用任何字符连接 userName
和 userType
,例如冒号:
userName:userType
,在loadUserByUsername方法中,你拆分得到
String[] parts = userName.split(":");
但是,当您将自定义参数加入用户名时,您必须自定义身份验证过滤器。在我的例子中,我添加了名称为 dmBhxhId
的新自定义参数。我创建 CustomUser:
public class CustomUser extends User {
private Long dmBhxhId;
public Long getDmBhxhId() {
return dmBhxhId;
}
public void setDmBhxhId(Long dmBhxhId) {
this.dmBhxhId = dmBhxhId;
}
public CustomUser(String username, String password, Collection<? extends GrantedAuthority> authorities,
Long dmBhxhId) {
super(username, password, authorities);
this.dmBhxhId = dmBhxhId;
}
public CustomUser(String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
}
}
我自定义身份验证过滤器
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private String extraParameter = "extra";
private String delimiter = ":";
/**
* Given an {@link HttpServletRequest}, this method extracts the username
* and the extra input values and returns a combined username string of
* those values separated by the delimiter string.
*
* @param request
* The {@link HttpServletRequest} containing the HTTP request
* variables from which the username client domain values can be
* extracted
*/
@Override
protected String obtainUsername(HttpServletRequest request) {
String username = request.getParameter(getUsernameParameter());
String extraInput = request.getParameter(getExtraParameter());
Map<String, String[]> map = request.getParameterMap();
String combinedUsername = username + getDelimiter() + extraInput;
return combinedUsername;
}
/**
* @return The parameter name which will be used to obtain the extra input
* from the login request
*/
public String getExtraParameter() {
return this.extraParameter;
}
/**
* @param extraParameter
* The parameter name which will be used to obtain the extra
* input from the login request
*/
public void setExtraParameter(String extraParameter) {
this.extraParameter = extraParameter;
}
/**
* @return The delimiter string used to separate the username and extra
* input values in the string returned by
* <code>obtainUsername()</code>
*/
public String getDelimiter() {
return this.delimiter;
}
/**
* @param delimiter
* The delimiter string used to separate the username and extra
* input values in the string returned by
* <code>obtainUsername()</code>
*/
public void setDelimiter(String delimiter) {
this.delimiter = delimiter;
}
}
在 SecurityConfiguration 文件中,我初始化了 CustomAuthenticationFilter
@Bean
public CustomAuthenticationFilter customAuthenticationFilter() throws Exception {
CustomAuthenticationFilter bcsAuthFilter = new CustomAuthenticationFilter();
bcsAuthFilter.setAuthenticationManager(authenticationManager());
bcsAuthFilter.setAuthenticationFailureHandler(ajaxAuthenticationFailureHandler);
bcsAuthFilter.setAuthenticationSuccessHandler(ajaxAuthenticationSuccessHandler);
bcsAuthFilter.setFilterProcessesUrl("/api/authentication");
bcsAuthFilter.setPostOnly(true);
bcsAuthFilter.setExtraParameter("dm_bhxh_id");
bcsAuthFilter.setUsernameParameter("j_username");
bcsAuthFilter.setPasswordParameter("j_password");
return bcsAuthFilter;
}
并在配置方法中调用
.addFilterBefore(bcsAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
看起来像
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.ignoringAntMatchers("/websocket/**").ignoringAntMatchers("/api/public/odts/**")
.and()
.addFilterBefore(bcsAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.addFilterAfter(new CsrfCookieGeneratorFilter(), CsrfFilter.class)
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
....
完成,希望对您有所帮助! 对不起,我的英文不好。