今天开始做SSM项目,建好表之后,开始做登录功能,项目是从上个项目直接移植过来的
言归正传
<form action="/login" method="post" id="loginForm">
这里是使用的表单提交的方式进行的, 所以我ctrl+h 搜索了一下
就找到了这2个地方,貌似也不对,后来就问了一下,以前是怎么登录登录的,各位不要见笑,本人以前是做android的,被拉来做临时工的
必须要在接口里继承UserDetailsService类,实现UserDetails loadUserByUsername(String username) throws UsernameNotFoundException的方法 如下所示
你没有看错,只有一个用户名,或是只是一个参数,但是丝毫没有体现出密码,所以本着工匠精神直接debug运行下去
只要是用户名或是电话号码正确,都能查询出用户数据,但是出抛出“账户或密码错误,请重试”的错误提示。所示输入一个错误的密码继续debug。
第1步,先搜索“账户或密码错误,请重试”错误提示信息。只搜索到一处
是继承了DaoAuthenticationProvider的自定义的验证提供类
第2步 点击super.authenticate(authentication),进入源码
这个类有点长
public abstract class AbstractUserDetailsAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware {
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication, messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.onlySupports",
"Only UsernamePasswordAuthenticationToken is supported"));
// Determine username
String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED"
: authentication.getName();
boolean cacheWasUsed = true;
UserDetails user = this.userCache.getUserFromCache(username);
if (user == null) {
cacheWasUsed = false;
try {
user = retrieveUser(username,
(UsernamePasswordAuthenticationToken) authentication);
}
catch (UsernameNotFoundException notFound) {
logger.debug("User '" + username + "' not found");
if (hideUserNotFoundExceptions) {
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials",
"Bad credentials"));
}
else {
throw notFound;
}
}
Assert.notNull(user,
"retrieveUser returned null - a violation of the interface contract");
}
try {
preAuthenticationChecks.check(user);
additionalAuthenticationChecks(user,
(UsernamePasswordAuthenticationToken) authentication);
}
catch (AuthenticationException exception) {
if (cacheWasUsed) {
// There was a problem, so try again after checking
// we're using latest data (i.e. not from the cache)
cacheWasUsed = false;
user = retrieveUser(username,
(UsernamePasswordAuthenticationToken) authentication);
preAuthenticationChecks.check(user);
additionalAuthenticationChecks(user,
(UsernamePasswordAuthenticationToken) authentication);
}
else {
throw exception;
}
}
postAuthenticationChecks.check(user);
if (!cacheWasUsed) {
this.userCache.putUserInCache(user);
}
Object principalToReturn = user;
if (forcePrincipalAsString) {
principalToReturn = user.getUsername();
}
return createSuccessAuthentication(principalToReturn, authentication, user);
}
}
太长了,不要看 ,我们看关键的代码
try {
user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);
}
user加载出来之后的数据
UserSession@763b173e: Username: 13000000000; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities
additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication); 进入实现类源码
public class DaoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
@SuppressWarnings("deprecation")
protected void additionalAuthenticationChecks(UserDetails userDetails,
UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
Object salt = null;
if (this.saltSource != null) {
salt = this.saltSource.getSalt(userDetails);
}
if (authentication.getCredentials() == null) {
logger.debug("Authentication failed: no credentials provided");
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials",
"Bad credentials"));
}
String presentedPassword = authentication.getCredentials().toString();
if (!passwordEncoder.isPasswordValid(userDetails.getPassword(),
presentedPassword, salt)) {
logger.debug("Authentication failed: password does not match stored value");
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials",
"Bad credentials"));
}
}
}
在这里验证密码,密码不对就会抛出异常。
开始只是知道登录框架已经帮我们实现了,但是不知道spring security这个框架,第一次使用,也不知道它的原理,更加不知道它是如何运行,不过现在知道的是,先查询出数据,再匹配密码是如正确。
但是又有一个疑问,为什么知道我的密码字段是password,我改成aabbcc试了试也可以
return new UserSession(record.getAccount(),record.getAabbcc(),authorities,record) 猜测是不是这里验证,把record.getAabbcc()改成其它的试试,我改成了record.getMobile() 也可以,真是奇怪
把jsp中的密码框改下
<input type="password2" name="password2" id="password2" class="form-control" placeholder="密码">
效果达到了,无论输入什么值都登录不上
原来是获取这里的值,但是它是怎么知道要与我数据库中的aabbcc对比的呢?有知道的可以告知下,谢谢!
网友评论