spring-security
之前的用户的账号、密码、权限都是在配置文件中写死了。
那么从数据库中获取呢?
从数据库查询用户信息
如果我们要从数据库动态查询用户信息,就必须按照spring security框架的要求提供一个实现UserDetailsService接口的实现类,并按照框架的要求进行配置即可。框架会自动调用实现类中的方法并自动进行密码校验。
实现步骤:
- 创建一个类实现UserDetailsService接口
import com.anone.pojo.User;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import java.util.ArrayList;
import java.util.List;
public class SpringSecurityUserService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//1.根据用户名查询数据库,获得User
User user = findUserByUname(username);
//2.判断是否为null
if (user == null) {
return null;
}
//3.把用户名,数据库的密码,以及查询出来的权限访问,创建UserDetails对象返回
List<GrantedAuthority> list = new ArrayList<GrantedAuthority>();//先把角色和权限写死,后面从数据库查询出来
list.add(new SimpleGrantedAuthority("add"));
list.add(new SimpleGrantedAuthority("delete"));
list.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
org.springframework.security.core.userdetails.User userDetails = new org.springframework.security.core.userdetails.User(username, "{noop}"+user.getPassword(), list);
return userDetails;
}
//模拟从数据库查询
private User findUserByUname(String username) {
if ("admin".equals(username)) {
User user = new User();
user.setUsername(username);
user.setPassword("123456");
return user;
}
return null;
}
}
2.在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:dubbo="http://code.alibabatech.com/schema/dubbo"
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/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<security:http security="none" pattern="/login.html" />
<!--1.配置需要权限才能访问的资源
auto-config属性: true 自动配置
use-expressions属性: false 不使用表达式
-->
<security:http auto-config="true" use-expressions="false">
...
<!--配置自定义登录页面
login-page: 登录页面; username-parameter:指定用户名的name;
password-parameter:指定密码的name;login-processing-url:指定登录的action;
authentication-failure-url:认证失败跳转的页面
authentication-success-forward-url:指定登录成功跳转的页面【默认是之前访问什么页面,登录成功后就跳转什么页面】
-->
<security:http auto-config="true" use-expressions="false">
...
<!--配置退出登录
logout-url:配置退出登录的路径; logout-success-url:配置成功退出登录后,跳转的页面;
invalidate-session:退出登录时销毁session
-->
<security:logout logout-url="/logout.do" logout-success-url="/login.html" invalidate-session="true"/>
</security:http>
<security:form-login
login-page="/login.html"
username-parameter="username"
password-parameter="password"
login-processing-url="/login.do"
authentication-failure-url="/login.html"
authentication-success-forward-url="/index.html"
/>
</security:http>
<!--关闭CsrfFilter过滤器-->
<security:http auto-config="true" use-expressions="false">
<security:csrf disabled="true"/>
</security:http>
<!--.配置认证管理器-->
<security:authentication-manager>
<security:authentication-provider user-service-ref="springSecurityUserService">
</security:authentication-provider>
</security:authentication-manager>
<bean id="springSecurityUserService" class="com.itheima.security.SpringSecurityUserService"></bean>
</beans>
运行启动maven的Tomcat插件即可。
对密码进行加密
实现步骤:
- 注册bcrypt对象, 告诉SpringSecurity使用这个加密方式
<!--.配置认证管理器-->
<security:authentication-manager>
<!--使用自定义的认证提供者-->
<security:authentication-provider user-service-ref="springSecurityUserService">
<!--指定密码加密码策略-->
<security:password-encoder ref="bCryptPasswordEncoder"/>
</security:authentication-provider>
</security:authentication-manager>
<!--注册密码加密对象-->
<bean id="bCryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
- 注入到代码里面 即可使用
在SpringSecurityUserService中注入
@Autowired
private BCryptPasswordEncoder encoder;
当我们使用的时候,它会自动加盐(底层是这样的,可以自行去看源码)
spring security其他的配置
配置多种校验规则
通过配置文件的形式来设置权限
修改spring-security.xml文件:
<!--只要认证通过就可以访问-->
<security:intercept-url pattern="/index.jsp" access="isAuthenticated()" />
<security:intercept-url pattern="/a.html" access="isAuthenticated()" />
<!--拥有add权限就可以访问b.html页面-->
<security:intercept-url pattern="/b.html" access="hasAuthority('add')" />
<!--拥有ROLE_ADMIN角色就可以访问c.html页面-->
<security:intercept-url pattern="/c.html" access="hasRole('ROLE_ADMIN')" />
<!--拥有ROLE_ADMIN角色就可以访问d.html页面,
注意:此处虽然写的是ADMIN角色,框架会自动加上前缀ROLE_-->
注解方式权限控制
Spring Security除了可以在配置文件中配置权限校验规则,还可以使用注解方式控制类中方法的调用。
实现步骤:
开启权限注解支持
在Controller的方法上面添加@PreAuthorize
第一步:在spring-security.xml文件中配置组件扫描,用于扫描Controller
<mvc:annotation-driven></mvc:annotation-driven>
<context:component-scan base-package="com.anone.controller"></context:component-scan>
第二步:在spring-security.xml文件中开启权限注解支持
<!--开启注解方式权限控制-->
<security:global-method-security pre-post-annotations="enabled" />
第三步:创建Controller类并在Controller的方法上加入注解进行权限控制
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/hello")
public class HelloController {
@RequestMapping("/add")
@PreAuthorize("hasAuthority('add')")//表示用户必须拥有add权限才能调用当前方法
public String add(){
System.out.println("add...");
return null;
}
@RequestMapping("/delete")
@PreAuthorize("hasRole('ROLE_ADMIN')")//表示用户必须拥有ROLE_ADMIN角色才能调用当前方法
public String delete(){
System.out.println("delete...");
return null;
}
}
注意:
一般是认证之后可以获取访问静态页面的权限,使用配置文件的方式
控制Controller的方法 建议使用注解
基本上都是配置文件+注解开发