1、导包
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<!--在spring框架的基础上加入springsecurity-->
2、改动web.xml
<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>
<!-- SpringSecurity自带的拦截器 -->
<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>
<!--在原有xml配置文件的基础上加入springSecurity监听器,拦截器以及读取springSecurity配置文件-->
3、核心配置文件spring-security.xml
<!-- 不进行认证也可以登录的页面 -->
<http pattern="/login.html" security="none"/>
<http pattern="/login_err.html" security="none"/>
<!-- 页面的拦截规则,是否开启SPEL表达式,默认为true -->
<http use-expressions="false">
<!-- 什么样的角色组可访问该资源下的所有文件,access代表的是哪个角色组,必须以ROLE开头
若use-expressions不配置默认为true时,那么access里面的内容应该为hasRole('ROLE_USER')
-->
<intercept-url pattern="/**" access="ROLE_USER"/>
<!-- 采用默认的表单登录 -->
<!--
login-page 默认登录页
default-target-url 登录成功跳转页
authentication-failure-url 登录失败跳转页
-->
<form-login login-page="/login.html" default-target-url="/index.html" authentication-failure-url="/login_err.html"/>
<!-- 当不使用security默认登录页时,有一个CSRF人员/角色认证器,需要进行关闭,使用security默认登录页时,进行自动关闭了 -->
<csrf disabled="true"/>
<!-- 要想iframe内嵌框架能够正常使用,那么frame-options的policy属性值必须设置为SAMEORIGIN -->
<headers>
<frame-options policy="SAMEORIGIN"/>
</headers>
<!-- 加入logout单标签之后支持退出操作,logout-url是退出路径,logout-success-url是成功退出路径,不配置默认跳往登录页面 -->
<logout/>
</http>
<!-- 认证管理器 -->
<authentication-manager>
<authentication-provider>
<user-service>
<user name="admin" password="123456" authorities="ROLE_USER"/>
</user-service>
</authentication-provider>
</authentication-manager>
- < http pattern="/login.html" security=“none”/>,表示spring-security框架不拦截此页面;
http标签对
- use-expressions=“false”,是否开启spring的SPEL表达式,默认为true;
- < intercept-url pattern="/ ** " access=“ROLE_USER”/>,access表示角色组,url pattern表示让access对应的角色组访问该路径下的页面;设置角色组时,必须是ROLE_开头命名,有两种方法,(1)use-expressions=“true”,如:ROLE_USER,可以直接写角色组名称;(2)use-expressions=“false”,角色组名要写hasRole(‘ROLE_USER’),单引号里面的是角色组名称
- form-login标签对,若什么属性都不配置,将启动springSecurity默认的登录页面,属性介绍如下:
-
login-page 默认登录页
default-target-url 登录成功跳转页
authentication-failure-url 登录失败跳转页
login-processing-url 登录路径
username-parameter 用户名对应的name值
password-parameter 密码对应的name值
always-use-default-target 登录成功之后始终跳往的页面,默认是 false
问:always-use-default-target是干嘛用的?
答:这个标签的作用是若用户先访问localhost:9101/admin/brand.html,默认跳转登录页面之后,不配置此属性,
假设用户登录成功,页面跳转到brand.html,而不是index.html,这时这个属性配置起作用了;配置always-use-default-target="true",
就是无论什么时候,登录成功就跳转到default-target-url对应的页面;
- csrf标签
-
当使用的是spring-security框架默认的登录页时,框架自动将csrf标签的disable属性设置为false;
-
当是自定义的登录页时,需要手动将disabled属性改为true;
-
csrf就像一座防火墙,如果不禁用,有的功能就实现不了;
authentication-manager认证管理器
<!--角色/用户认证管理器-->
<authentication-manager>
<!--角色/用户认证管理提供者-->
<authentication-provider>
<!--用户服务-->
<user-service>
<!--创建一个用户,设置用户的登录用户名为admin,password为123456,authorities对应的角色组为ROLE_USER-->
<user name="admin" password="123456" authorities="ROLE_USER"/>
</user-service>
</authentication-provider>
</authentication-manager>
商家入驻实例
改动核心配置文件
<!-- 不进行登录也可以访问的页面 -->
<http pattern="/*.html" security="none"/>
<http pattern="/css/**" security="none"/>
<http pattern="/img/**" security="none"/>
<http pattern="/js/**" security="none"/>
<http pattern="/plugins/**" security="none"/>
<!-- 对商家入驻应该放行 -->
<http pattern="/seller/add.do" security="none"/>
<!-- 页面的拦截规则,是否开启SPEL表达式,默认为true -->
<http use-expressions="false">
<!-- 什么样的角色组可访问该资源下的所有文件,access代表的是哪个角色组,必须以ROLE开头
若use-expressions不配置默认为true时,那么access里面的内容应该为hasRole('ROLE_USER')
-->
<intercept-url pattern="/admin/**" access="ROLE_SELLER"/>
<!-- 采用默认的表单登录 -->
<!--
login-page 默认登录页
default-target-url 登录成功跳转页
authentication-failure-url 登录失败跳转页
login-processing-url 登录路径
username-parameter 用户名对应的name值
password-parameter 密码对应的name值
always-use-default-target 登录成功之后始终跳往的页面,默认是 false
-->
<form-login login-page="/shoplogin.html" default-target-url="/admin/index.html" authentication-failure-url="/shoplogin.html" always-use-default-target="true" />
<!-- 当不使用security默认登录页时,有一个CSRF人员/角色认证器,需要进行关闭,使用security默认登录页时,进行自动关闭了 -->
<csrf disabled="true"/>
<!-- 要想iframe内嵌框架能够正常使用,那么frame-options的policy属性值必须设置为SAMEORIGIN -->
<headers>
<frame-options policy="SAMEORIGIN"/>
</headers>
<!-- 加入logout单标签之后支持退出操作,logout-url是退出路径,logout-success-url是成功退出路径,不配置默认跳往登录页面 -->
<logout/>
</http>
<!-- 认证管理器 -->
<authentication-manager>
<authentication-provider user-service-ref="userDetailService">
<password-encoder ref="bCryptEncoder"/>
</authentication-provider>
</authentication-manager>
<!-- 创建一个beans,加载刚刚创建好的自定义登录实体类 -->
<beans:bean id="userDetailService" class="com.pinyougou.service.UserDetailsServiceImpl">
<beans:property name="sellerService" ref="sellService"/>
</beans:bean>
<dubbo:application name="pinyougou-manager-web" />
<dubbo:registry address="zookeeper://192.168.4.169:2181"/>
<dubbo:reference id="sellService" interface="com.pinyougou.sellergoods.service.SellerService" />
<beans:bean id="bCryptEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
商家入驻密码使用bCrypt加密方式
@RequestMapping("/add")
public Result add(@RequestBody TbSeller seller){
//使用bcrypt加密方式
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String encode = passwordEncoder.encode(seller.getPassword());
seller.setPassword(encode);
try {
sellerService.add(seller);
return new Result(true, "增加成功");
} catch (Exception e) {
e.printStackTrace();
return new Result(false, "增加失败");
}
}
自定义用户认证类
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.pinyougou.pojo.TbSeller;
import com.pinyougou.sellergoods.service.SellerService;
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> muiltRoles = new ArrayList<GrantedAuthority>();
muiltRoles.add(new SimpleGrantedAuthority("ROLE_SELLER"));
TbSeller tbSeller = sellerService.findOne(username);
if(tbSeller!=null){
// TODO Auto-generated method stub
if(tbSeller.getStatus().equals("1")){
return new User(username, tbSeller.getPassword(), muiltRoles );
}else{
return null;
}
}else{
return null;
}
}}
获取登录用户
@RequestMapping("/name")
public Map<String,Object> getLoginName(){
Map<String,Object> map = new HashMap<String,Object>();
//获取上下文对象,获取认证对象,获取名称
String name = SecurityContextHolder.getContext().getAuthentication().getName();
map.put("loginName", name);
return map;
}
前台用户登录
<form class="sui-form" action="/login" method="post" id="loginForm">
<div class="input-prepend"><span class="add-on loginname"></span>
<input id="prependedInput" type="text" placeholder="邮箱/用户名/手机号" class="span2 input-xfat" name="username">
</div>
<div class="input-prepend"><span class="add-on loginpwd"></span>
<input id="prependedInput" type="password" placeholder="请输入密码" class="span2 input-xfat" name="password">
</div>
<div class="setting">
<label class="checkbox inline"><input name="m1" type="checkbox" value="2" checked="">自动登录</label>
<span class="forget">忘记密码?</span>
</div>
<div class="logined">
<a class="sui-btn btn-block btn-xlarge btn-danger" onclick="document:loginForm.submit()" target="_blank">登 录</a>
</form>
<!---loginForm是form的名称,提交表单可使用document:loginForm.submit()->
<!--退出采用的是<a href="/logout"></a>,注意路径问题即可-->