Spring Security——认证(登录)、密码加密、权限控制
认证(登录)
导入jar包或者依赖
导入spring-security所需要的jar包
或者Maven依赖
<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>
在web.xml文件中配置认证过滤器
<!--认证过滤器-->
<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>
创建spring-security.xml配置文件
<?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:http security="none" pattern="/html/login.html" />
<!-- 配置拦截的规则
auto-config:是否使用框架提供的登录页面
use-expressions:是否使用spel表达式
如果使用spel表达式多个权限:hasAnyRole('ROLE_USER','ROLE_ADMIN')
-->
<security:http auto-config="false" use-expressions="true">
<!--配置拦截的请求地址,任何请求地址都必须拥有ROLE_USER的权限
access:默认配置时它应该是一个以逗号分隔的角色列表,如 "ROLE_USER,ROLE_ADMIN"
请求的用户只需拥有其中的一个角色就能成功访问对应的URL
使用spel表达式多个权限:hasAnyRole('ROLE_USER','ROLE_ADMIN')
-->
<security:intercept-url pattern="/**" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')" />
<!-- auto-config为true,不需要在配置下面信息 <security:form-login /> -->
<!--配置自己的登录页面-->
<security:form-login login-page="/html/login.html" login-processing-url="/login"
username-parameter="username" password-parameter="password"
authentication-failure-url="/html/login.html" default-target-url="/index.jsp"/>
<!--配置退出-->
<security:logout invalidate-session="true" logout-url="/logout" logout-success-url="/html/login.html"></security:logout>
</security:http>
<!--配置认证(登录)信息:认证管理器-->
<security:authentication-manager>
<!--认证信息提供者
user-service-ref:引入用户服务
-->
<security:authentication-provider user-service-ref="userService">
</security:authentication-provider>
</security:authentication-manager>
</beans>
配置拦截的规则
认证管理器:
创建用户服务 UserService
UserService接口继承 UserDetailsService接口
UserService实现类实现 loadUserByUsername( ) 方法
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper mapper;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
//s 就是登录页面传来的username
UserInfo info = mapper.selectUserAndRoleByUsername(s);
//将用户的用户名、密码以及List<SimpleGrantedAuthority>填入security定义的user中
// org.springframework.security.core.userdetails.User;
User user = new User(info.getUsername(),info.getPassword(),getRole(info.getRoles()));
return user;
}
//将角色信息存入SimpleGrantedAuthority对象中,在封装进List集合中
public List<SimpleGrantedAuthority> getRole(List<Role> roles){
List<SimpleGrantedAuthority> l = new ArrayList<>();
for (Role role:roles) {
SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(role.getRoleName());
l.add(simpleGrantedAuthority);
}
return l;
}
运行结果:
不满足角色权限的用户,重新进入login.html
密码加密
1、配置 密码编码器passwordEncoder
在 springsecurity.xml中,配置passwordEncoder,交给Spring容器进行实例化
<!--实例化 密码编码器-->
<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></bean>
2、在认证管理器中引入 密码编码器
以便以在认证登录的时候,进行解密
<!--配置认证(登录)信息:认证管理器-->
<security:authentication-manager>
<!--认证信息提供者
user-service-ref:引入用户服务
-->
<security:authentication-provider user-service-ref="userService">
<!--引入密码编码器,认证的时候,进行解密-->
<security:password-encoder ref="passwordEncoder"></security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
3、 在UserService实现类中进行加密
添加用户的时候,进行加密
权限控制
服务器端 方法级别权限控制
在springmvc.xml中,开启权限控制——面向切面的自动代理
<!--开启权限控制 面向切面的自动代理-->
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
@Secured注解方式
在springsecurity.xml文件中,开启Secured方法注解
<!--开启服务器端secured方法注解-->
<security:global-method-security secured-annotations="enabled"></security:global-method-security>
对删除商品进行权限控制:
@Secured("ROLE_ADMIN")//@Secured注解,方法级别的控制
只有ROLE_ADMIN角色才可以调用该方法
JSR250注解方式
导入jar包
在springsecurity.xml文件中,开启JSR250方法注解
<!--开启服务器端JSR250方法方法注解-->
<security:global-method-security jsr250-annotations="enabled"></security:global-method-security>
对删除商品进行权限控制:
@RolesAllowed("ROLE_ADMIN")// JSR250注解方式
@PermitAll //允许所有角色访问
@DenyAll //拒绝所有角色访问
表达式注解
开启服务器端表达式方法注解
<!--开启服务器端表达式方法注解-->
<security:global-method-security pre-post-annotations="enabled"></security:global-method-security>
对对删除商品进行权限控制:
@PreAuthorize("hasAnyRole('ROLE_ADMIN')") //表达式注解
@PreAuthorize("authentication.principal.username == 'wang'") //只有用户名为"wang"的用户,才可以调用
页面端标签权限控制
导入jar包
在JSP页面导入taglib 标签库
<%@taglib prefix="security" uri="http://www.springframework.org/security/tags"%>
使用authentication获取用户信息
<security:authentication property="principal.username"></security:authentication>
使用authorize控制标签的显示
<security:authorize access="hasAnyRole('ROLE_ADMIN')">标签</security:authorize>
例如:
<security:authorize access="hasAnyRole('ROLE_ADMIN')">
<li id="system-setting"><a
href="${pageContext.request.contextPath}/product/findAll">
<i class="fa fa-circle-o"></i> 产品管理
</a></li>
</security:authorize>