1. 认证和授权概念
认证:系统提供用于识别用户身份的功能。认证的目的是让系统知道是谁。
授权:用户认证认证后,需要进行为用户授权,指定当前用户具有哪些功能。对后台系统进行权限控制,其本质是对用户进行认证和授权。
2. 权限模块模型
表关系如图:
认证过程:只需要用户表t_user,在用户登录时可以查询用户表进行校验,判断用户输入的用户名和密码是否正确。
授权过程:首先根据用户查询角色,根据角色查询对应的菜单,用户可以看到哪些菜单,根据用户的角色查询对应的权限。
3. 什么是spring security?
3.1 spring-security的简介
由spring提供的安全认证的服务框架。官网:Spring Security
引入对应的pom.xml依赖:
<!--spring安全框架-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
常用的权限框架对比:
1.** spring security**:
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。
它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
2. Apache的**shiro**框架:
Apache Shiro是一个开源安全框架,提供身份验证、授权、密码学和会话管理。Shiro框架具有直观、易用等特性,同时也能提供健壮的安全性。
3.2 spring security的快速入门
index.jsp
<h1>hello Spring Security...</h1>
配置web.xml
<!--配置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>
<!--加载spring-security配置文件-->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-security.xml</param-value>
spring-security.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<!--auto-config为true表示自动应用配置
use-expressions 是否使用表达式来描述权限
-->
<security:http auto-config="true" use-expressions="true">
<!--配置拦截规则pattern:拦截规则 access:指定访问角色或权限 -->
<security:intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')"></security:intercept-url>
</security:http>
<!--配置认证管理器-->
<security:authentication-manager>
<!--配置认证提供者-->
<security:authentication-provider>
<security:user-service>
<security:user name="小梦" password="{noop}123" authorities="ROLE_ADMIN" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
测试效果:
跳转spring security自定义的登录页面:
4. 改进Spring Security入门案例
4.1. 配置可匿名(不登陆)访问的资源
<!--配置资源可以匿名访问-->
<!--<security:http security="none" pattern="/pages/user.jsp"></security:http>
<security:http security="none" pattern="/pages/role.jsp"></security:http>-->
<security:http security="none" pattern="/pages/**"></security:http>
4.2. 使用指定的登录页面
<!--配置自定义的登录页面-->
<security:form-login
login-page="/login.jsp"
username-parameter="username"
password-parameter="password"
login-processing-url="/login.do"
default-target-url="/index.jsp"
authentication-failure-url="/login.jsp"
></security:form-login>
<!--关闭CsrfFilter过滤器-->
<security:csrf disabled="true"></security:csrf>
4.3 从数据库中查询用户信息
按照spring security框架的要求提供一个实现UserDetailsService接口的实现类,并按照框架要求进行配置。自动调用实现类中的方法并自动校验。
public class UserService implements UserDetailsService {
public static Map<String, User> map= new HashMap<>();
static {
User user1 = new User();
user1.setUsername("xiaomeng");
user1.setPassword("123");
User user2 = new User();
user2.setUsername("xinru");
user2.setPassword("123");
map.put(user1.getUsername(), user1);
map.put(user2.getUsername(), user2);
}
//根据用户名查询数据库的用户信息
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println("========username======>"+username);
User user = map.get(username);
if (user == null){
return null;
} else {
List<GrantedAuthority> list = new ArrayList<>();
list.add(new SimpleGrantedAuthority("permission_A"));
list.add(new SimpleGrantedAuthority("permission_B"));
if (username.equals("xiaomeng")){
list.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
org.springframework.security.core.userdetails.User securityUser = new org.springframework.security.core.userdetails.User(username, "{noop}"+user.getPassword(),list);
return securityUser;
}
}
}
<!--配置认证管理器-->
<security:authentication-manager>
<!--配置认证提供者-->
<security:authentication-provider user-service-ref="userService">
<!--<security:user-service>
<security:user name="xiaomeng" password="{noop}123" authorities="ROLE_ADMIN"/>
</security:user-service>-->
</security:authentication-provider>
</security:authentication-manager>
<!--配置UserService实现类交给spring容器管理权-->
<bean id="userService" class="cn.hfnu.service.UserService"></bean>
4.4 对密码进行加密控制
一般情况下用户的密码进行加密后保存到数据库。常见的加密方式: 3DES、AES、DES:使用对称加密算法。MD5、SHA1:使用单向HASH算法建立彩虹表进行查表破解。bcrypt;将salt随机并混入最终加密后后的密码,验证时无需单独提供之前的salt。
<!--指定对密码进行加密对象-->
<security:password-encoder ref="passwordEncoder"></security:password-encoder>
<!--配置密码加密对象-->
<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<!--开启spring注解-->
<context:annotation-config></context:annotation-config>
public class UserService2 implements UserDetailsService {
@Autowired
private BCryptPasswordEncoder passwordEncoder;
public Map<String, User> map= new HashMap<>();
public void initUserData(){
User user1 = new User();
user1.setUsername("xiaomeng");
user1.setPassword(passwordEncoder.encode("abc")); //密码加密
User user2 = new User();
user2.setUsername("xinru");
user2.setPassword(passwordEncoder.encode("123"));
map.put(user1.getUsername(), user1);
map.put(user2.getUsername(), user2);
}
//根据用户名查询数据库的用户信息
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
initUserData();
System.out.println("========username======>"+username);
User user = map.get(username);
if (user == null){
return null;
} else {
List<GrantedAuthority> list = new ArrayList<>();
list.add(new SimpleGrantedAuthority("permission_A"));
list.add(new SimpleGrantedAuthority("permission_B"));
if (username.equals("xiaomeng")){
list.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
org.springframework.security.core.userdetails.User securityUser = new org.springframework.security.core.userdetails.User(username, user.getPassword(),list);
return securityUser;
}
}
}
4.5 配置多种校验规则
<!--只要认证通过就可以访问-->
<security:intercept-url pattern="/pages/user.jsp" access="isAuthenticated()"/>
<!--拥有add权限就可以访问-->
<security:intercept-url pattern="/pages/role.jsp" access="hasAuthority('add')"/>
<!--拥有ROLE_ADMIN角色就可以访问-->
<security:intercept-url pattern="/pages/service1.jsp" access="hasRole('ROLE_ADMIN')"/>
<!--拥有ROLE_ADMIN角色就可以访问-->
<security:intercept-url pattern="/pages/service2.jsp" access="hasRole('ADMIN')"/>
4.6 注解方式进行权限控制
<!--配置组件扫描-->
<mvc:annotation-driven></mvc:annotation-driven>
<context:component-scan base-package="cn.hfnu.controller"></context:component-scan>
<!--开启注解方式的权限控制-->
<security:global-method-security pre-post-annotations="enabled"/>
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/add")
@PreAuthorize("hasAuthority('add')") //调用该方法用户必须拥有add权限
public String add(){
return "success";
}
@RequestMapping("/delete")
@PreAuthorize("hasRole('ROLE_ADMIN')") //调用该方法用户必须拥有ROLE_ADMIN角色
public String delete(){
return "success";
}
}
4.7 退出登录
<!--配置退出登录-->
<security:logout logout-url="/logout.do" logout-success-url="/login.jsp" invalidate-session="true"/>
4.8 小结
spring-security.xml配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<!--配置资源可以匿名访问-->
<!--<security:http security="none" pattern="/pages/user.jsp"></security:http>
<security:http security="none" pattern="/pages/role.jsp"></security:http>-->
<security:http security="none" pattern="/login.jsp"></security:http>
<!--auto-config为true表示自动应用配置
use-expressions 是否使用表达式来描述权限
-->
<security:http auto-config="true" use-expressions="true">
<!--只要认证通过就可以访问-->
<security:intercept-url pattern="/pages/user.jsp" access="isAuthenticated()"/>
<!--拥有add权限就可以访问-->
<security:intercept-url pattern="/pages/role.jsp" access="hasAuthority('add')"/>
<!--拥有ROLE_ADMIN角色就可以访问-->
<security:intercept-url pattern="/pages/service1.jsp" access="hasRole('ROLE_ADMIN')"/>
<!--拥有ROLE_ADMIN角色就可以访问-->
<security:intercept-url pattern="/pages/service2.jsp" access="hasRole('ADMIN')"/>
<!--配置拦截规则pattern:拦截规则 access:指定访问角色或权限 -->
<security:intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')"></security:intercept-url>
<!--配置自定义的登录页面-->
<security:form-login
login-page="/login.jsp"
username-parameter="username"
password-parameter="password"
login-processing-url="/login.do"
default-target-url="/index.jsp"
authentication-failure-url="/login.jsp"
></security:form-login>
<!--关闭CsrfFilter过滤器-->
<security:csrf disabled="true"></security:csrf>
<!--配置退出登录-->
<security:logout logout-url="/logout.do" logout-success-url="/login.jsp" invalidate-session="true"/>
</security:http>
<!--配置认证管理器-->
<security:authentication-manager>
<!--配置认证提供者-->
<security:authentication-provider user-service-ref="userService2">
<!--<security:user-service>
<security:user name="xiaomeng" password="{noop}123" authorities="ROLE_ADMIN"/>
</security:user-service>-->
<!--指定对密码进行加密对象-->
<security:password-encoder ref="passwordEncoder"></security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
<!--配置UserService实现类交给spring容器管理权-->
<bean id="userService" class="cn.hfnu.service.UserService"></bean>
<bean id="userService2" class="cn.hfnu.service.UserService2"></bean>
<!--配置密码加密对象-->
<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<!--开启spring注解-->
<context:annotation-config></context:annotation-config>
<!--配置组件扫描-->
<mvc:annotation-driven></mvc:annotation-driven>
<context:component-scan base-package="cn.hfnu.controller"></context:component-scan>
<!--开启注解方式的权限控制-->
<security:global-method-security pre-post-annotations="enabled"/>
</beans>
以上内容对SpringSecurity的学习记录,后期我从数据库中查询具体的用户并赋予角色和权限。如果你认真看完,对SpringSecurity框架进行认证和授权有了初步的认识。你如果进来”在看“,就点击”在看“,点个赞,你的赞是我学习的最大动力。坚持一件事情不容易,点个”在看“,点个”赞“,你会变好看,一次点赞,一次好运。