认证实际就是登录和设置权限(就是立Flag,Flag通过授权才能有具体的相应的作用)
登录就是校验用户名和密码,通常情况下用户名和密码是存储在数据库中
登录名和密码存储方式:
1、通过配置文件
查找 SecurityProperties,可以确定配置属性
spring.security.user.name=sys
spring.security.user.password=123
2、通过配置类(内存认证)
@EnableWebSecurity //开启 public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() //内存 .passwordEncoder(new BCryptPasswordEncoder()) //指定加密方式 .withUser("marw") .password(new BCryptPasswordEncoder().encode("123")) //使用加密 .roles("ADMIN"); } }
加密方式有很多,官方推荐使用BCryptPasswordEncoder,其他的加密方式可以通过PasswordEncoder关键字查看
3、通过配置类(JDBC认证)
https://docs.spring.io/spring-security/site/docs/5.3.9.RELEASE/reference/html5/#servlet-authentication-jdbc
查看UserDetailsService接口
loadUserByUsername方法主要作用根据用户获取用户,用户类型UserDetails,主要信息有用户名,密码,权限等等
查找UserDetails的实现类User
自定义登录:需要实现UserDetailsService接口并返回User对象,User对象中包含的信息也要是用户名、密码和权限等信息。
@Service public class UserDetailsServiceImpl implements UserDetailsService { @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { List<GrantedAuthority> auth= AuthorityUtils.commaSeparatedStringToAuthorityList("role"); return new User("jdbcUser",new BCryptPasswordEncoder().encode("123") ,auth); } }
使用自定义登录逻辑,需要在配置类中指定UserDetailsService具体实现
@EnableWebSecurity //开启 public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired UserDetailsService UserDetailsServiceImpl; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(UserDetailsServiceImpl).passwordEncoder(new BCryptPasswordEncoder()); } }
Jdbc具体实现
1、Sql语句
CREATE TABLE users( username VARCHAR(50) NOT NULL PRIMARY KEY, PASSWORD VARCHAR(500) NOT NULL, authority VARCHAR(50) NOT NULL );
角色
管理员 admin
来宾 guest
权限
管理权限 sys :访问管理页面
浏览权限 part :访问指定页面
用户
admin用户是管理员身份具有管理权限
guest用户是来宾身份具有部分权限
2、创建pojo
@Repository public class Users { private String username; private String password; private String authority; ... ... }
3、添加依赖
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
4、创建mapper
@Mapper public interface UserMapper { public Users findUserByUsername(String username); }
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.marw.springbootwebmvc.mapper.UserMapper"> <select id="findUserByUsername" parameterType="String" resultType="com.marw.springbootwebmvc.pojo.Users"> SELECT * FROM users WHERE username=#{username} </select> </mapper>
5、mybatis整合(配置application.yaml)
spring: datasource: username: root password: root url: jdbc:mysql://192.168.116.136:3306/springbootdb?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8 driver-class-name: com.mysql.cj.jdbc.Driver mybatis: mapper-locations: classpath:mapper/*.xml
6、创建UserDetailsService接口实现类,获取数据库中用户信息
@Service public class UserDetailsServiceImpl implements UserDetailsService { @Autowired UserMapper userMapper;
@Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { Users user = userMapper.findUserByUsername(s); List<GrantedAuthority> auth= AuthorityUtils.commaSeparatedStringToAuthorityList(user.getAuthority());//设置权限 return new User(user.getUsername(),new BCryptPasswordEncoder().encode(user.getPassword()) ,auth); } }
7、configure(AuthenticationManagerBuilder auth)方法认证,成功就可以访问系统,但是系统会有多个模块,不应该是所有人登录就可以访问的,这样就需要对访问模块的不同设置不同的权限
@EnableWebSecurity //开启 public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired UserDetailsService UserDetailsServiceImpl; //认证:登录验证和设置权限(包含角色和权限) @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(UserDetailsServiceImpl).passwordEncoder(new BCryptPasswordEncoder()); } }
8、首先创建多个模块,Admin模块,Test模块,首页,admin 访问 admin模块,guest访问test模块,首页只要登录就可以访问
admin模块代码

@RestController @RequestMapping("/admin") public class AdminController { @GetMapping("/index") public String index(){ return "Hello Admin"; } @GetMapping("/add") public String add(){ return "添加方法"; } }
test模块代码

@RestController @RequestMapping("/test") public class TestController { @GetMapping("/test") public String test(){ return "Hello test"; } @GetMapping("/index") public String index(){ return "Hello index"; } }
首页代码

@RestController @RequestMapping("any") public class IndexController { @GetMapping("index") public String index(){ return "Any idnex"; } }
9、授权
在SecurityConfig配置类中增加以下代码
//授权:针对url的设置 @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/test/**").hasAuthority("part") .antMatchers("/admin/**").hasAuthority("sys") .anyRequest().authenticated() .and().formLogin(); }