1、导入依赖
<dependencies>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.0.1.RELEASE</version>
</dependency>
</dependencies>
2、创建Spring-security配置文件,并在web.xml中设置读取配置文件
Spring-security配置文件约束
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
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">
</beans>
web.xml配置启动时读取Springsecurity配置文件:
<!--context 的监听器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--服务启动时,读取配置文件-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
3、用户认证类的编写
首先,我们需要创建一个继承了org.springframework.security.core.userdetails.UserDetailsService;的认证类,并实现public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException方法,该方法的返回值为UserDetails类(封装当前认证用户信息)。Springsecurity在进行认证时会传入用户名,如果找不到用户名(抛出异常)、或者密码错误,则跳转到失败页面
springsecurity的用户密码需要加密
package com.ZepngLin.service.imp;
import com.ZepngLin.dao.UserDao;
import com.ZepngLin.domain.Role;
import com.ZepngLin.domain.UserInfo;
import com.ZepngLin.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
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.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service("userService")
public class UserServiceImp implements UserService{
@Autowired
UserDao dao;
@Autowired
private BCryptPasswordEncoder passwordEncoder; //用于加密密码
/**
*
* @param s 用户名
* @return 认证对象的信息
* @throws UsernameNotFoundException 未找到该用户
*/
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
List<SimpleGrantedAuthority> authorities = new ArrayList<>(); //存储权限列表
UserInfo userInfo = dao.findByUsername(s); //获取用户信息
for(Role role : userInfo.getRoles()){
authorities.add(new SimpleGrantedAuthority(role.getRoleName())); //取出用户拥有的角色
}
return new User(userInfo.getUsername(),userInfo.getPassword(),authorities); //实现了UserDetails接口的实现类
}
@Override
public List<UserInfo> findAll() {
return dao.findAll();
}
@Override
public void save(UserInfo user) {
user.setPassword(passwordEncoder.encode(user.getPassword())); //密码加密
dao.save(user);
}
@Override
public UserInfo findById(int id) {
return dao.findById(id);
}
@Override
public List<Role> findOtherRoles(int id) {
return dao.findOtherRoles(id);
}
//添加角色
@Override
public void addRoleToUser(int id, Integer[] roleIds) {
for (int roleId : roleIds) {
dao.addRoleToUser(id,roleId);
}
}
}
4、Spring-security配置文件的编写
权限名需要加上ROLE前缀、配置完成后将只有拥有ROLE_GUEST角色的用户可以浏览页面
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
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:global-method-security jsr250-annotations="enabled"/>-->
<!--<security:global-method-security pre-post-annotations="enabled"/>-->
<security:global-method-security secured-annotations="enabled"/>
<!-- 配置不过滤的资源(静态资源及登录相关) -->
<security:http security="none" pattern="/pages/login.jsp" />
<security:http security="none" pattern="/pages/failer.jsp" />
<security:http pattern="/css/**" security="none"/>
<security:http pattern="/img/**" security="none"/>
<security:http pattern="/plugins/**" security="none"/>
<security:http auto-config="true" use-expressions="false">
<!-- 配置资料连接,表示任意路径都需要ROLE_GUEST权限 -->
<security:intercept-url pattern="/**" access="ROLE_GUEST" />
<!-- 自定义登陆页面,login-page 自定义登陆页面 authentication-failure-url 用户权限校验失败之
后才会跳转到这个页面,如果数据库中没有这个用户则不会跳转到这个页面。
default-target-url 登陆成功后跳转的页面。 注:登陆页面用户名固定 username,密码
password,action:login -->
<!--login-processing-url :配置表单提交路径-->
<security:form-login login-page="/pages/login.jsp"
login-processing-url="/login.do"
username-parameter="username"
password-parameter="password"
<!--失败、成功、默认跳转页面-->
authentication-failure-url="/pages/failer.jsp"
authentication-success-forward-url="/pages/main.jsp"
default-target-url="/pages/main.jsp"
/>
<!-- 登出, invalidate-session 是否删除session logout-url:登出处理链接 logout-successurl:
登出成功页面
注:登出操作 只需要链接到 logout.do即可登出当前用户 -->
<security:logout invalidate-session="true" logout-url="/logout.do"
logout-success-url="/login.jsp" />
<!-- 关闭CSRF,默认是开启的 -->
<security:csrf disabled="true" />
</security:http>
<!--加密方式-->
<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<security:authentication-manager>
<!--提供认证的方式,useService为我们自定义配置的类,已在Spring配置文件中被扫描加入IOC容器-->
<security:authentication-provider user-service-ref="userService">
<!--配置加密方式-->
<security:password-encoder ref="passwordEncoder"/>
</security:authentication-provider>
</security:authentication-manager>
<!--配置使用SPEL表达式-->
<bean id="webexpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler" />
</beans>
5、几种权限控制方法的总结:
(1)通过xml配置各个访问路径所需要的角色:
所有路径都需要ROLE_GUEST权限:<security:intercept-url pattern="/**" access=“ROLE_GUEST” />
(2)通过security 标签库对JSP组件进行可见控制
导入标签库:<%@ taglib prefix=“security” uri=“http://www.springframework.org/security/tags” %>
使用标签包含需要进行权限控制的代码块:
<!-- 只有ROLE_ROOT角色的用户才可见 -->
<security:authorize access="hasRole('ROLE_ROOT')">
<div>
代码块
</div>
</security:authorize>
(3)通过注解的方式