SpringSecurity开发步骤
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作
1.开发思路
1. 拦截用户请求 登录页的路径为("../login" method="post")
2. 当前登陆的用户是谁?
3. 配置访问某一个资源需要什么角色?
4. 当前登陆用户具有什么角色?
5. 认证/登陆 授权
2.开发步骤
1.第一步: 引入依赖(spring + spring 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文件(spring配置文件 + DelegatingFilterProxy-委托代理过滤器)
<?xmlversion="1.0"encoding="UTF-8"?>
<web-appxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
< 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>
</ web-app>
3.配置spring配置文件
<?xmlversion="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" >
<http pattern="/login.html"security="none"></ http>
<http pattern="/css/**"security="none"></ http>
<http pattern="/img/**"security="none"></ http>
<http pattern="/js/**"security="none"></ http>
<http pattern="/plugins/**"security="none"></ http>
< http use-expressions = " false" >
< intercept-url pattern = " /**" access = " ROLE_SELLER" />
< form-login login-page = " /login.html" default-target-url = " /admin/index.html"
authentication-failure-url = " /login.html"
always-use-default-target = " true" />
< csrf disabled = " true" />
< headers>
<frame-optionspolicy="SAMEORIGIN"/>
</ headers>
< logout logout-url = " " logout-success-url = " " />
</ http>
< authentication-manager>
< authentication-provider user-service-ref = " userDetailService" >
< password-encoder ref = " bcryptEncoder" > </ password-encoder>
</ authentication-provider>
</ authentication-manager>
< beans: bean id = " userDetailService" class = " com.oranges.service.UserDetailsServiceImpl" >
< beans: property name = " sellerService" ref = " sellerService" > </ beans: property>
</ beans: bean>
< dubbo: application name = " pinyougou-shop-web" />
< dubbo: registry address = " zookeeper://192.168.25.135:2181" />
< dubbo: reference id = " sellerService"
interface = " com.oranges.sellergoods.service.SellerService" > </ dubbo: reference>
< beans: bean id = " bcryptEncoder"
class = " org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" >
</ beans: bean>
</ beans: beans>
4.前端页面的表单提交方式
< form action = " ../login" method = " post" >
</ form>
5.获取通过框架登陆后登陆者的姓名
@RestController
@RequestMapping ( "/login" )
publicclassLoginController {
@RequestMapping ( "name" )
publicMap name ( ) {
String name= SecurityContextHolder. getContext ( )
. getAuthentication ( ) . getName ( ) ;
Mapmap= newHashMap ( ) ;
map. put ( "loginName" , name) ;
returnmap ;
}
}
6.编辑后台代码认证类
public class UserDetailsServiceImpl implements UserDetailsService {
private SellerService sellerService;
public void setSellerService ( SellerService sellerService) {
this . sellerService = sellerService;
}
@Override
public UserDetails loadUserByUsername ( String username) throws UsernameNotFoundException {
System. out. println ( "经过了UserDetailsServiceImpl" ) ;
List< GrantedAuthority> grantAuths= new ArrayList ( ) ;
grantAuths. add ( new SimpleGrantedAuthority ( "ROLE_SELLER" ) ) ;
TbSeller seller = sellerService. findOne ( username) ;
if ( seller!= null) {
if ( seller. getStatus ( ) . equals ( "1" ) ) {
return new User ( username, seller. getPassword ( ) , grantAuths) ;
} else {
return null;
}
} else {
return null;
}
}
}
6.注销登陆
<logout logout-url="" logout-success-url=""/>
<!-- 前台页面的提交路径为 "../logout" -->
3.密码加密: BCrypt
1.了解
用户表的密码通常使用MD5等不可逆算法加密后存储,为防止彩虹表破解更会先使用一个特定的字符串(如域名)加密,然后再使用一个随机的salt(盐值)加密。特定字符串是程序代码中固定的,salt是每个密码单独随机,一般给用户表加一个字段单独存储,比较麻烦。BCrypt算法将salt随机并混入最终加密后的密码,验证时也无需单独提供之前的salt,从而无需单独处理salt问题。
2.加密实现: BCryptPasswordEncoder
@RequestMapping ( "/add" )
public Result add ( @RequestBodyTbSeller seller) {
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder ( ) ;
String password = passwordEncoder. encode ( seller. getPassword ( ) ) ;
seller. setPassword ( password) ;
try {
sellerService. add ( seller) ;
returnnew Result ( true , "增加成功" ) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
returnnew Result ( false , "增加失败" ) ;
}
}
3.spring文件的配置: 告诉系统该密码是以什么样子的形式加密的
< beans: bean id = " bcryptEncoder"
class = " org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
< authentication-manager alias = " authenticationManager" >
< authentication-provider user-service-ref = ' userDetailService' >
< password-encoder ref = " bcryptEncoder" > </ password-encoder>
</ authentication-provider>
</ authentication-manager>