springSecurity集成的项目必须是集成了spring的项目
1.引入jar
<!--安全框架security-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
2.在项目的web.xml中配置security配置,让项目启动时容器加载spring-security.xml配置文件及配置拦截路径,spring-security会根据配置文件生成对应的Filter进行拦截
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-security.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<filter>
<filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3.spring-security.xml配置内容:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<!--1.不拦截资源路径和请求-->
<http pattern="/shoplogin.html" security="none"/>
<http pattern="/register.html" security="none"/>
<http pattern="../seller/add.do" security="none"/>
<http pattern="/css/**" security="none"/>
<http pattern="/img/**" security="none"/>
<http pattern="/js/**" security="none"/>
<http pattern="/plugins/**" security="none"/>
<!--2.拦截规则配置 use-expressions:是否SPEL表达式-->
<http use-expressions="true">
<logout/>
<!--
logout-url:退出的地址,会自动生成,可以省略
logout-success-url:退出后跳转的地址,如果不配置,默认是登陆配置指定的登录页
<logout logout-url="" logout-success-url=""/>
-->
<!--拦截所有请求,如果上面的不拦截匹配到了,这里就不会生效-->
<intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')"></intercept-url>
<!--
login-page:指定登录页面
default-target-url:登录成功后跳转页面
authentication-failure-url:登录失败跳转页面
always-use-default-target:登录成功后总是跳转至配置的default-target-url页面
-->
<form-login login-page="/shoplogin.html" default-target-url="/admin/index.html" authentication-failure-url="/shoplogin.html"
always-use-default-target="true"/>
<!--关闭CSRF伪造请求-->
<csrf disabled="true"/>
<headers>
<!--指定页面中内嵌的iframe页面也不拦截-->
<frame-options policy="SAMEORIGIN"/>
</headers>
</http>
<!--3.认证管理器-->
<authentication-manager>
<authentication-provider user-service-ref="userDetailsService">
<!--认证比较密码时将密码进行bcrypt算法加密,数据库存储密码时也进行bcrypt算法加密存储-->
<password-encoder ref="bcryptEncoder"></password-encoder>
</authentication-provider>
</authentication-manager>
<beans:bean id="userDetailsService" class="com.pyg.service.UserDetailsServiceImpl">
<beans:property name="sellerService" ref="sellerService"></beans:property>
</beans:bean>
<!--BCrypt加密-->
<beans:bean id="bcryptEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
</beans:beans>
4.security安全认证类(sellerService 需要配置在spring容器中否则下面获取不到):
import com.pyg.pojo.TbSeller;
import com.pyg.sellergoods.service.SellerService;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import java.util.ArrayList;
import java.util.List;
/**
* 安全认证类
*/
public class UserDetailsServiceImpl implements UserDetailsService{
//这里不能使用@Reference注解来注入service,因为UserDetailsServiceImpl不是注解方式加入到spring容器
//这里使用spring配置bean的方式加入,需要dubbo采用非注解方式声明sellerService,这样sellerService会被加入到spring容器中
//在UserDetailsServiceImpl的bean的配置中增加<beans:property ...通过ref来引用sellerService
private SellerService sellerService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
TbSeller seller = sellerService.findOne(username);//得到商家
if(seller != null){
if("1".equals(seller.getStatus())){
return new User(username,seller.getPassword(),authorities);
}
}
return null;
}
public void setSellerService(SellerService sellerService) {
this.sellerService = sellerService;
}
}
5.执行过程:
spring-security从前台登录页面获取到用户名和密码,用户点击登录发送指定请求:/login ,安全认证类会被触发执行loadUserByUsername 方法,参数就是用户输入的用户名,下面就是根据用户名查询数据库是否存在这样的用户,如果存在则比较密码,比对成功则放行,不成功根据配置跳转至所指定失败页面。
注意:上面的密码比较,在数据库的密码需要通过BCrypt算法加密,如:
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String password = passwordEncoder.encode(seller.getPassword());
seller.setPassword(password);
sellerService.add(seller);
如果框架使用了dubbo来获取service服务,那么在dubbo的配置中需要注意:上面的安全认证类UserDetailsServiceImpl 是通过配置bean的方式加入到spring容器中,所以dubbo也不要使用扫描包的方式,即:不通过@Reference 方式来获取sellerService,这样获取不到。dubbo配置通过非注解方式来获取sellerService,这样会把sellerService加入spring容器中。
<dubbo:reference id="sellerService" interface="com.pyg.sellergoods.service.SellerService"></dubbo:reference>