品优购_day04

品优购_day04

1. Spring Security框架

1.1 Spring Security简介

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

1.2 spring-security.xml

<!--配置不拦截的资源-->
	<security:http pattern="/login.html" security="none"></security:http>
	<security:http pattern="/css/**" security="none"></security:http>
	<security:http pattern="/img/**" security="none"></security:http>
	<security:http pattern="/js/**" security="none"></security:http>
	<security:http pattern="/plugins/**" security="none"></security:http>
<!--页面拦截规则-->
	<security:http use-expressions="false">
		<!--配置具体的拦截规则-->
		<security:intercept-url pattern="/**" access="ROLE_SELLER"/>
		<!--定义跳转的具体页面-->
		<security:form-login login-page="/login.html" 
							login-processing-url="/login.do" 
							default-target-url="/admin/index.html"
							authentication-failure-url="/login.html"
							always-use-default-target="true"/>
		<!--关闭跨域请求-->
		<security:csrf disabled="true"/>
		<!--显示框架页-->
		<security:headers>
			<security:frame-options policy="SAMEORIGIN"/>
		</security:headers>
		
		<!--用户退出-->
		<security:logout invalidate-session="true" logout-url="/logout.do"/>
	</security:http>

<!-- 认证管理器 -->
	<security:authentication-manager>
		<security:authentication-provider>
			<security:user-service>
<!--可直接在这里配置用户名,密码,权限-->
				<security:user name="admin" password="123" authorities="ROLE_SELLER"/>
			</security:user-service>		
		</security:authentication-provider>	
	</security:authentication-manager>
  1. intercept-url 表示拦截页面

/* 表示的是该目录下的资源,只包括本级目录不包括下级目录

/** 表示的是该目录以及该目录下所有级别子目录的资源

  1. form-login :为开启表单登陆;

login-processing-url:登录时提交的地址,默认为/login.do,可不写;

default-target-url:指定了成功进行身份验证和授权后默认呈现给用户的页面;

authentication-failure-url:指定了身份验证失败时跳转到的页面;

always-use-default-target:指定了是否在身份验证通过后总是跳转到default-target-url属性指定的URL。

  1. use-expressions 为是否使用使用 Spring 表达式语言( SpEL ),默认为ttrue ,如果开启,则拦截的配置应该写成以下形式

<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />

  1. <security:csrf disabled="true"/>:关闭跨域请求

关闭csrf ,因为这里是html页面,如果不加会出现错误:Http status 403-Invalid CSRF token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN',如果是jsp页面,则不用关闭,要携带x-csrf-token头信息,必须是jsp页面。

CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。

  1. <security:frame-options policy="SAMEORIGIN"/>

如果你系统中使用了框架页,如adminLTE需要设置框架页的策略为SAMEORIGIN,框架页才会显示。

  1. <security:logout invalidate-session="true" logout-url="/logout.do"/>

用于退出登录,添加此行,然后点击退出时访问/logout.do即可。invalidate-session:清空已定义的session ,而不是清空session里的值,logout-url:退出的地址,默认是/logout.do。

1.3 登录页面

<form id="loginForm" action="/login" method="post"  >
		<input name="username" type="text" placeholder="邮箱/用户名/手机号" class="span2 input-xfat">
		<input name="password" type="password" placeholder="请输入密码" class="span2 input-xfat">
		<a onclick="document:loginForm.submit()" target="_blank">登录</a>
</form>

1.4 显示登录用户名

可单独写一个LoginController,然后在页面初始化时访问即可。

@RestController
@RequestMapping("/login")
public class LoginController {
	@RequestMapping("/name")
	public Map getLoginName() {
	String loginName=
  SecurityContextHolder.getContext().getAuthentication().getName();
		Map map=new HashMap();
		map.put("loginName", loginName);
		return map;
	}
}

Spring Security使用一个Authentication对象来描述当前用户的相关信息。SecurityContextHolder中持有的是当前用户的SecurityContext,而SecurityContext持有的是代表当前用户相关信息的Authentication的引用,可以通过getName()或getPrincipal方法获取当前登录用户的用户名。getName()是直接获取当前线程的操作对象,框架已经封装进去, 而getPrincipal()需要自己实例化去判断,可以加入业务逻辑判断,再进行返回。

2. 商家登录与安全控制

完成商家系统登陆与安全控制,商家账号来自数据库,并实现密码加密。

2.1 自定义认证类

在pinyougou-shop-web创建com.pinyougou.service包,包下创建类UserDetailsServiceImpl.java 实现UserDetailsService接口

public class UserServiceImpl implements UserDetailsService {
	private SellerService ss;//不用注解方式,用配置方式注入时,必须有一个set方法
	public void setSs(SellerService ss) {
		this.ss = ss;
	}
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{
		//构建角色列表
		List<GrantedAuthority> list=new ArrayList();
		list.add(new SimpleGrantedAuthority("ROLE_SELLER"));
		//到数据库中查询用户
        TbSeller ts=ss.findOne(username);
		if(ts!=null&&ts.getStatus().equals("1")) {
			return new User(username,ts.getPassword(),list);
		}
		return null;
	}
}

2.2 在spring-security.xml添加如下配置

重难点:引用dubbo服务获取在远程的SellerService

<!--不过滤添加用户操作-->
<security:http pattern="/seller/add.do" security="none"></security:http>

<!-- 认证管理器 -->
	<!-- 切换成数据库中的用户名和密码 -->
    <security:authentication-manager>
        <security:authentication-provider user-service-ref="userService">
            <!-- 配置加密的方式 -->
<security:password-encoder ref="bCryptPasswordEncoder"/>
        </security:authentication-provider>
    </security:authentication-manager>
	
	<!--配置认证类-->
	<bean id="userService" class="com.pinyougou.service.UserServiceImpl">
		<property name="ss" ref="sellerService"></property>
	<!--name="ss"这个名字与UserServiceImpl中的ss相同-->
</bean>
	
	<!--
UserServiceImpl用到了SellerService,而UserServiceImpl在18pinyougou-shop-web,而SerllerService在18pinyougou-sellergoods-interface,即SellerService在远程,所以要引用dubbo服务获取-->
	<!-- 引用dubbo 服务 -->
	<dubbo:application name="18pinyougou-shop-web"></dubbo:application>
	<dubbo:registry address="zookeeper://192.168.25.130:2181"></dubbo:registry>
	<dubbo:reference id="sellerService" interface="com.pinyougou.sellergoods.service.SellerService"></dubbo:reference>

2.3 密码加密

2.3.1 BCrypt加密算法

用户表的密码通常使用MD5等不可逆算法加密后存储,为防止彩虹表破解更会先使用一个特定的字符串(如域名)加密,然后再使用一个随机的salt(盐值)加密。 特定字符串是程序代码中固定的,salt是每个密码单独随机,一般给用户表加一个字段单独存储,比较麻烦。 BCrypt算法将salt随机并混入最终加密后的密码,验证时也无需单独提供之前的salt,从而无需单独处理salt问题。

2.3.2 使用BCrypt进行加密存储

创建密码加密工具类

public class PasswordEncoderUtils {
	private static BCryptPasswordEncoder bpe=new BCryptPasswordEncoder();
	//返回加密后的密码
	public static String passwordEncode(String password) {
		return bpe.encode(password);
	}
}

2.3.3 在spring-security.xml配置加密类

<security:authentication-manager>
        ......
            <!-- 配置加密的方式 -->
<security:password-encoder ref="bCryptPasswordEncoder"/>
        </security:authentication-provider>
</security:authentication-manager>

<!-- 配置加密类 -->
    <!--声明该加密类为一个名为bCryptPasswordEncoder的bean-->
    <bean id="bCryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
原文地址:https://www.cnblogs.com/ALiWang/p/12885069.html