SpringSecurity安全框架和Bcrypt加密

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">
    <!-- 加载spring的核心配置文件 -->
	<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">

    <!-- security="none"设置此资源不被拦截 -->
    <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>

    <!-- 页面拦截规则 -->
    <!--
        1. http : 表示页面的拦截规则
        2. intercept-url: 表示拦截的页面
            /*  表示的是该目录下的资源,只包括本级目录不包括下级目录
            /** 表示的是该目录以及该目录下所有级别子目录的资源
            use-expressions为是否使用使用 Spring 表达式语言(SpEL),默认为true ,如果开启
        3. form-login: 表示开启表单登陆功能
            3.1 login-page: 登陆页
            3.2 default-target-url: 登陆成功后默认跳转的页面
            3.3 authentication-failure-url: 登陆失败默认跳转的页面
            3.4 csrf disabled="true"关闭csrf ,如果不加会出现错误
            3.5 always-use-default-target: 指定了是否在身份验证通过后总是跳转到default-target-url属性指定的URL
            3.6 logout : 注销操作
                logout-url : 退出的地址,默认的地址为 /logout
                logout-success-url: 默认为 index.html
        4. authentication-manager: 认证管理器, 判断用户需要什么样的角色
            user-service-ref: 全类名(该类实现了UserDetailsService接口)
    -->
    <http use-expressions="false">
        <!-- 当前用户必须有ROLE_USER的角色 才可以访问根目录及所属子目录的资源 -->
        <intercept-url pattern="/**" access="ROLE_SELLER"/>
        <!--<intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>-->
        <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 服务 -->
    <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.前端页面的表单提交方式
<!-- 提交路径必须为 login, 提交方式必须为post -->
<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")){
				//grantAuths 用户所具有的角色
				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>

猜你喜欢

转载自blog.csdn.net/Orangesss_/article/details/82805938