第一步写配置文件 :编写安全认证的配置文件 spring-security.xml
security="none" 设置此资源不被拦截.
login-page:指定登录页面。
authentication-failure-url:指定了身份验证失败时跳转到的页面。
default-target-url:指定了成功进行身份验证和授权后默认呈现给用户的页面。
csrf disabled="true" 关闭 csrf ,如果不加会出现错误
<?xml version="1.0" encoding="UTF-8"?>
<bean:beans xmlns="http://www.springframework.org/schema/security"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:bean="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://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 在权限认证之前访问资源需要放行 -->
<http pattern="/shoplogin.html" security="none"></http>
<http pattern="/error.html" security="none"></http>
<http pattern="/register.html" security="none"></http>
<http pattern="/css/**" security="none"></http>
<http pattern="/js/**" security="none"></http>
<http pattern="/img/**" security="none"></http>
<http pattern="/plugins/**" security="none"></http>
<!-- 商家入驻url -->
<http pattern="/seller/add" security="none"></http>
<!-- http安全控制规则 -->
<http>
<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<!-- 表单认证 -->
<form-login login-page="/shoplogin.html"
default-target-url="/admin/index.html" always-use-default-target="true"
authentication-failure-url="/error.html" login-processing-url="/login" />
<!-- 屏蔽跨域 -->
<csrf disabled="true" />
<!-- 配置ifram访问 -->
<headers>
<frame-options policy="SAMEORIGIN" />
</headers>
<!-- 推出登录配置 -->
<!-- logout: spring security 安全框架自动生成推出地址:/logout -->
<logout logout-success-url="/shoplogin.html" />
</http>
<!-- 引用dubbo 服务 以便在认证类中能调用service方法经常数据查询-->
<dubbo:application name="pinyougou-shop-web" />
<dubbo:registry address="zookeeper://192.168.66.66:2181" />
<!-- xml引入sellerService对象 -->
<dubbo:reference id="sellerService"
interface="com.pyg.manager.service.SellerService"></dubbo:reference>
<!-- 配置认证管理器 -->
<authentication-manager>
<authentication-provider user-service-ref="userDetailsServiceImpl">
<password-encoder ref="passwordEncoder"></password-encoder>
</authentication-provider>
</authentication-manager>
<!-- 自定义认证类 -->
<bean:bean id="userDetailsServiceImpl"
class="com.pyg.shop.service.impl.UserDetailsServiceImpl">
<bean:property name="sellerService" ref="sellerService"></bean:property>
</bean:bean>
<!-- 定义spring security安全加密算法对象 -->
<bean:bean id="passwordEncoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></bean:bean>
</bean:beans>
导包pom.xml
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
web.xml springSecurityFilterChain:名字不要变
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 指定加载的配置文件 ,通过参数contextConfigLocation加载 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/*.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- spring security 安全控制过滤器 -->
<!-- 使用过滤器拦截请求,对这些请求进行安全验证 -->
<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>
<!--安全认证 -->
第三步:创建配置文件里自定义认证类的类,在里面为安全认证添加用户名 密码
细节:如下我们看到早这个类总我们需要调用业务层查询用户登录 但是在这个安全认证的框架中我们不能直接使用@Autowired 我们需要在配置文件配置中使用xml的方法引用数据
并使其其get set方法。
MD5加密解密
//给商家密码加密 controller层 加密后的密码保存数据库(security特有的md5加密不可逆的)
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String newpwd = passwordEncoder.encode(seller.getPassword());
//把加密后密码设置到对象中
seller.setPassword(newpwd);
配置管理认证器把页面的密码也加密进行传递 (看配置文件)
<password-encoder ref="passwordEncoder"></password-encoder>
package com.pyg.shop.service.impl;
import java.util.ArrayList;
import java.util.List;
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 com.pyg.manager.service.SellerService;
import com.pyg.pojo.TbSeller;
public class UserDetailsServiceImpl implements UserDetailsService {
private SellerService sellerService;
public SellerService getSellerService() {
return sellerService;
}
public void setSellerService(SellerService sellerService) {
this.sellerService = sellerService;
}
//以下为固定写法 定义一个GrantedAuthority list集合 然后添加角色 查询数据库用户信息 进行封装
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
//定义角色封装集合
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
//添加角色 与配置文件的角色对应
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
//调用商家服务对象,查询商家密码
TbSeller seller = sellerService.findOne(username);
return new User(username, seller.getPassword(), authorities);
}
}
注册用户/修改密码等 进行密码加密处理保存数据库:
BCrypt 加密算法
用户表的密码通常使用 MD5 等不可逆算法加密后存储,为防止彩虹表破解更会先使用 一个特定的字符串(如域名)加密,然后再使用一个随机的 salt(盐值)加密。 特定字符 串是程序代码中固定的,salt 是每个密码单独随机,一般给用户表加一个字段单独存储,比 较麻烦。 BCrypt 算法将 salt 随机并混入最终加密后的密码,验证时也无需单独提供之前的 salt,从而无需单独处理 salt 问题。
使用方法:
需求分析:在用户注册时,保存用户密码的时候先将密码加密再进行保存, 登录时把用户输入的密码也进行加密再与数据库保存的加密密码对比
/**
* 增加用户 新增用户
* @param seller
* @return
*/
@RequestMapping("/add")
public PygResult add(@RequestBody TbSeller seller){
try {
//给商家密码加密
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String newpwd = passwordEncoder.encode(seller.getPassword());
//把加密后密码设置到对象中
seller.setPassword(newpwd);
//保存
sellerService.add(seller);
return new PygResult(true, "增加成功");
} catch (Exception e) {
e.printStackTrace();
return new PygResult(false, "增加失败");
}
}