Java 这个Spring安全示例究竟是如何工作的?
我对SpringSecurity是个新手,我对教程中的配置有些怀疑 这是用于将spring安全配置导入项目的spring security.xml文件:Java 这个Spring安全示例究竟是如何工作的?,java,spring,spring-mvc,jakarta-ee,spring-security,Java,Spring,Spring Mvc,Jakarta Ee,Spring Security,我对SpringSecurity是个新手,我对教程中的配置有些怀疑 这是用于将spring安全配置导入项目的spring security.xml文件: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmln
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<security:http>
<security:intercept-url pattern="/springLogin" access="permitAll"/>
<security:intercept-url pattern="/doSpringLogin" access="permitAll"/>
<security:intercept-url pattern="/myprofile" access="hasRole('ROLE_USER')"/>
<security:intercept-url pattern="/springHome" access="hasRole('ROLE_USER')"/>
<security:intercept-url pattern="/products" access="hasRole('ROLE_USER')"/>
<security:intercept-url pattern="/springLogout" access="permitAll"/>
<security:intercept-url pattern="/springLogin?error=true" access="permitAll"/>
<security:form-login login-page="/springLogin" login-processing-url="/doSpringLogin"
default-target-url="/springHome" authentication-failure-url="/springLogin?error=true"
username-parameter="username" password-parameter="password"
/>
<security:csrf disabled="true"/>
<security:logout logout-url="/springLogout" logout-success-url="/springLogin"/>
</security:http>
<bean id="userDetailsServiceImpl" class="com.demo.security.UserDetailsServiceImpl"></bean>
<bean id="authenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="userDetailsServiceImpl"></property>
</bean>
<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
<constructor-arg name="providers">
<list>
<ref bean="authenticationProvider"/>
</list>
</constructor-arg>
</bean>
<security:authentication-manager>
<security:authentication-provider user-service-ref="userDetailsServiceImpl">
<security:password-encoder hash="plaintext"></security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
</beans>
我把它分成几个部分。第一个是标记内容
它包含以下内容:
<security:intercept-url pattern="/springLogin" access="permitAll"/>
我认为这意味着与/springLogin资源相关的页面在
<security:intercept-url pattern="/myprofile" access="hasRole('ROLE_USER')"/>
表示与/myprofile资源相关的资源仅可供设置了角色的登录用户(主体)访问
这个推理正确吗
然后在上一个配置文件中有:
1) authenticationManagerbean的声明:
<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
<constructor-arg name="providers">
<list>
<ref bean="authenticationProvider"/>
</list>
</constructor-arg>
</bean>
我认为Spring使用它来用主体对象(例如web应用程序的所有用户)和权限填充SecurityContext(具体的主体可以做什么)
这个推理正确吗
此对象将必须提供主体信息的自动验证提供者bean列表作为构造函数arg(例如,与特定主体关联的角色)
在本例中,提供了一个DaoAuthenticationProvider类的实现,该类将具有name=“userDetailsService”的bean作为属性,如下所示:
<bean id="userDetailsServiceImpl" class="com.demo.security.UserDetailsServiceImpl"></bean>
public class UserDetailsServiceImpl implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
System.out.println(username);
User user = RegisteryDAO.getUserDAO().getUserByUsername(username);
if(user == null){
return null;
}
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority(user.getRole()));
UserDetails userDetails = new org.springframework.security.core.userdetails.
User(user.getUsername(), user.getPassword(), true, true, true, true, authorities);
return userDetails;
}
}
这是UserDetailsServiceImpl类的一个实例,这个:
<bean id="userDetailsServiceImpl" class="com.demo.security.UserDetailsServiceImpl"></bean>
public class UserDetailsServiceImpl implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
System.out.println(username);
User user = RegisteryDAO.getUserDAO().getUserByUsername(username);
if(user == null){
return null;
}
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority(user.getRole()));
UserDetails userDetails = new org.springframework.security.core.userdetails.
User(user.getUsername(), user.getPassword(), true, true, true, true, authorities);
return userDetails;
}
}
公共类UserDetailsServiceImpl实现UserDetailsService{
@凌驾
公共用户详细信息loadUserByUsername(字符串用户名)
抛出UsernameNotFoundException{
System.out.println(用户名);
User User=RegisteryDAO.getUserDAO().getUserByUsername(用户名);
if(user==null){
返回null;
}
列表权限=新建ArrayList();
添加(新的SimpleGrantedAuthority(user.getRole());
UserDetails UserDetails=new org.springframework.security.core.UserDetails。
用户(User.getUsername(),User.getPassword(),true,true,true,authorities);
返回用户详细信息;
}
}
那么到底发生了什么
使用调试器,在我看来,当te用户尝试访问特定页面时,此loadUserByUsername()返回与登录用户相关的UserDetails对象,其中包含表示与特定登录用户相关联的角色的列表(例如先前的角色\u用户)
然后我认为弹簧会自动使用
<security:intercept-url pattern="/myprofile" access="hasRole('ROLE_USER')"/>
检查用户是否已将propper角色设置到上一个列表中
如果它将请求转发给处理此Http请求的控制器方法,否则请避免此HttpRequest到达此控制器方法,并显示一个页面,说明用户无法访问此资源。以下是您所询问的一些概念和问题的解释
AuthenticationManager
AuthenticationManager
是负责处理身份验证
请求的组件。身份验证请求可能是用户名/密码登录的实例
对于其他实现,请参阅
AuthenticationManager
还包含AuthenticationProvider
实现的集合。这些组件能够处理特定的Authentication
类型,并且AuthenticationManager
对它们进行迭代,试图找到一个能够处理传递给它的验证的组件。如果它找到了一个,它将调用它,并显示Authentication
对象,如果成功,则返回完全填充的Authentication
对象(否则将抛出AuthenticationException
)
AuthenticationProvider
如上所述,AuthenticationProvider
处理特定类型的Authentication
请求。例如,DaoAuthenticationProvider
在被AuthenticationManager
调用时将执行以下步骤:
- 获取传递给它的
UsernamePasswordAuthenticationToken
- 使用提供给它的
UserDetailsService
服务实现(在您的情况下是userdetailserviceinpl
)按用户名查找用户
- 使用
PasswordEncoder
和SaltSource
检查身份验证令牌中提供的密码(如果指定)
- 如果身份验证成功,则返回填充的身份验证对象(
UsernamePasswordAuthenticationToken
),该对象包含主体、凭据并标记为
- 如果身份验证失败,将抛出
AuthenticationException
DaoAuthenticationProvider
您正在使用的能够处理UsernamePasswordAuthenticationToken
请求的身份验证提供程序。通常是表单登录等等。您可以通过查看其支持()来查看身份验证提供程序支持哪些类型
方法实现,在DaoAuthenticationProvider
的情况下如下所示:
public boolean supports(Class<?> authentication) {
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
}
使用调试器似乎
<security:intercept-url pattern="/myprofile" access="hasRole('ROLE_USER')" />