acegi
源码学习之用户登录篇
一、查看
applicationContext-acegi-security.xml
配置文件,涉及到登录的配置为:
1
.
<
bean
id
=
"authenticationProcessingFilter"
class
=
"org.javajohn.test.plugins.security.UserAuthenticationProcessingFilter"
>
<
property
name
=
"authenticationManager"
ref
=
"authenticationManager"
/>
<
property
name
=
"authenticationFailureUrl"
>
<
value
>
/login.jsp?login_error=1
</
value
>
</
property
>
<
property
name
=
"defaultTargetUrl"
>
<
value
>
/index.jsp
</
value
>
</
property
>
<
property
name
=
"filterProcessesUrl"
>
<
value
>
/j_acegi_security_check
</
value
>
</
property
>
<
property
name
=
"userManager"
ref
=
"userManager"
/>
<
property
name
=
"rememberMeServices"
ref
=
"rememberMeServices"
/>
<
property
name
=
"exceptionMappings"
>
<
value
>
org.acegisecurity.AuthenticationException=/login.jsp?login_error=user_psw_error
org.acegisecurity.concurrent.ConcurrentLoginException=/login.jsp?login_error=too_many_user_error
</
value
>
</
property
>
</
bean
>
2
.
<
bean
id
=
"authenticationManager"
class
=
"org.acegisecurity.providers.ProviderManager"
>
<
property
name
=
"providers"
>
<
list
>
<
ref
local
=
"daoAuthenticationProvider"
/>
<
bean
class
=
"org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider"
>
<
property
name
=
"key"
value
=
"javajohnKey"
/>
</
bean
>
<
bean
class
=
"org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider"
>
<
property
name
=
"key"
value
=
"javajohnKey"
/>
</
bean
>
</
list
>
</
property
>
</
bean
>
3
.
<
bean
id
=
"daoAuthenticationProvider"
class
=
"org.acegisecurity.providers.dao.DaoAuthenticationProvider"
>
<
property
name
=
"userDetailsService"
ref
=
"jdbcDaoImpl"
/>
<
property
name
=
"userCache"
>
<
bean
class
=
"org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache"
>
<
property
name
=
"cache"
>
<
bean
class
=
"org.springframework.cache.ehcache.EhCacheFactoryBean"
>
<
property
name
=
"cacheManager"
>
<
bean
class
=
"org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
/>
</
property
>
<
property
name
=
"cacheName"
value
=
"userCache"
/>
</
bean
>
</
property
>
</
bean
>
</
property
>
<
property
name
=
"passwordEncoder"
ref
=
"passwordEncoder"
/>
</
bean
>
4
.
<
bean
id
=
"jdbcDaoImpl"
class
=
"org.acegisecurity.userdetails.jdbc.JdbcDaoImpl"
>
<
property
name
=
"dataSource"
ref
=
"dataSource"
/>
<
property
name
=
"usersByUsernameQuery"
>
<
value
>
select loginid,passwd,1 from users where status='1' and loginid = ?
</
value
>
</
property
>
<
property
name
=
"authoritiesByUsernameQuery"
>
<
value
>
select u.loginid,p.name from
users u,roles r,permissions p,user_role ur,role_permis rp
where
u.id=ur.user_id and
r.id=ur.role_id and
p.id=rp.permis_id and
r.id=rp.role_id and
p.status='1' and u.loginid=?
</
value
>
</
property
>
</
bean
>
二、程序流程:
1
.登录的时候执行的过滤为
authenticationProcessingFilter
,查看其实现为
org.bookStore.test.plugins.security.UserAuthenticationProcessingFilter
,该类继承自
org.acegisecurity.ui.webapp.AuthenticationProcessingFilter
,又继承自
org.acegisecurity.ui.AbstractProcessingFilter
,这时候看到了
doFilter()
该方法取了
web
层传过来的
request
和
response
,然后对登录路径执行了判断等操作,接下来执行至
authResult = attemptAuthentication(httpRequest);
2
.从类继承关系上找到该方法的实现来自
AuthenticationProcessingFilter
,执行的逻辑为先取出
web
层传过来的用户名和密码接着将得到的信息包装为
UsernamePasswordAuthenticationToken
:
public
UsernamePasswordAuthenticationToken(Object principal, Object credentials) {
super
(
null
);
this
.
principal
= principal;
this
.
credentials
= credentials;
setAuthenticated(
false
);
}
3
.接下来执行了
setDetails(request, authRequest);
将
request
实例赋给
authRequest
的属性。
4
.调用
authenticationManager
的
authenticate(authRequest)
方法。
5
.程序转至
authenticationManager
内执行。该类继承自
org.acegisecurity. AbstractAuthenticationManager
,执行方法
authenticate(authRequest)
:
public final Authentication authenticate(Authentication authRequest)
throws AuthenticationException {
try {
Authentication authResult = doAuthentication(authRequest);
copyDetails(authRequest, authResult);
return authResult;
} catch (AuthenticationException e) {
e.setAuthentication(authRequest);
throw e;
}
}
doAuthentication(authRequest)
来自
ProviderManager
该方法执行了其
providers
中的方法
authenticate(Authentication authentication)
6
.此方法中调用了
retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication)
该方法内按
web
层用户输入的用户名和密码从数据库内比较是否有该用户,如果有则将其
user
表内对应的信息包装为
UserDetail(
接口
,
实际为
User
的实例
)
的
List
对象,并将该用户相应的权限包装为
GrantedAuthorityImpl
对象的
List
集合对象。至此程序返回至(
3.
)继续执行
7
.继续执行
org.acegisecurity.ui.AbstractProcessingFilter
的
successfulAuthentication(
HttpServletRequest request,
HttpServletResponse response,
Authentication authResult){
......
SecurityContextHolder.getContext().setAuthentication(authResult);//
将包装好的
UsernamePasswordAuthenticationToken
对象保存至系统上下文
......
}
8
.登录执行完毕。