一、基于配置的认证与授权
新建controller
包
在该包下新建三个控制器,AdminController,AppController,UserController
分别创建测试API
/**
* 模拟后台相关Api接口
*/
@RequestMapping("/admin/api")
@RestController
public class AdminController {
@RequestMapping(value = "/hi",method = RequestMethod.GET)
public String hi(){
return "hi,admin.";
}
}
/**
* 模拟对外公开的Api接口
*/
@RequestMapping("/app/api")
@RestController
public class AppController {
@RequestMapping(value = "/hi", method = RequestMethod.GET)
public String hi() {
return "hi,app.";
}
}
/**
* 模拟用户相关Api接口
*/
@RequestMapping("/user/api")
@RestController
public class UserController {
@RequestMapping(value = "/hi", method = RequestMethod.GET)
public String hi() {
return "hi,user.";
}
}
配置资源授权
配置configure
修改之前的配置
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/api/**").hasRole("ADMIN")
.antMatchers("/user/api/**").hasRole("USER")
.antMatchers("/app/api/**").permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/myLogin.html")
// 指定处理登录请求的路径,修改请求的路径,默认为/login
.loginProcessingUrl("/mylogin")
// 使登录页面不设限访问
.permitAll()
.and()
.csrf().disable();
}
antMatchers()
一个采用ANT模式的URL匹配器
? 表示匹配任意单个字符
* 表示匹配0或任意数量字符
** 表示匹配0或更多的目录
重启服务
访问api http://localhost:8080/app/api/hi
访问成功 页面显示 hi,app.
访问api http://localhost:8080/user/api/hi
跳转到登录页面
输入自定义的用户名密码
登录成功,页面却报403错误,表示授权失败
认证已经通过,授权失败,以为我们配置的.antMatchers("/user/api/**").hasRole("USER")
,需要用户具有USER角色权限
修改配置文件application.yml
spring:
security:
user:
name: caoshenyang
password: 123456
roles: USER
给用户添加USER权限
重启项目
访问api http://localhost:8080/user/api/hi
登录成功后,页面显示hi,user.
访问api http://localhost:8080/admin/api/hi
出现同样情况
修改配置文件application.yml
给用户添加上ADMIN权限
重启项目
访问正常,页面显示hi,admin.
二、基于内存的多用户设置
1. 实现自定义的UserDetailsService
@Bean
public UserDetailsService userDetailsService(){
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
//MD5 加密 明文 111 加密后 698d51a19d8a121ce581499d7b701668
//noop 明文
manager.createUser(User.withUsername("aa").password("{MD5}698d51a19d8a121ce581499d7b701668").roles("USER").build());
manager.createUser(User.withUsername("bb").password("{noop}222").roles("USER").build());
return manager;
}
注意:SpringSecurity5.x 以上版本需要配置加密否则会出现以下异常
There is no PasswordEncoder mapped for the id "null"
SpringSecurity5.x 加密方式采用{Id}password
的格式配置
我们可以看一下PasswordEncoderFactories自带的加密方式
public class PasswordEncoderFactories {
public static PasswordEncoder createDelegatingPasswordEncoder() {
String encodingId = "bcrypt";
Map<String, PasswordEncoder> encoders = new HashMap();
encoders.put(encodingId, new BCryptPasswordEncoder());
encoders.put("ldap", new LdapShaPasswordEncoder());
encoders.put("MD4", new Md4PasswordEncoder());
encoders.put("MD5", new MessageDigestPasswordEncoder("MD5"));
encoders.put("noop", NoOpPasswordEncoder.getInstance());
encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
encoders.put("scrypt", new SCryptPasswordEncoder());
encoders.put("SHA-1", new MessageDigestPasswordEncoder("SHA-1"));
encoders.put("SHA-256", new MessageDigestPasswordEncoder("SHA-256"));
encoders.put("sha256", new StandardPasswordEncoder());
encoders.put("argon2", new Argon2PasswordEncoder());
return new DelegatingPasswordEncoder(encodingId, encoders);
}
private PasswordEncoderFactories() {
}
}
重新启动
输入账号密码
登录成功
此配置会覆盖原先application.yml
中的配置
2. 通过congfigure
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.passwordEncoder(NoOpPasswordEncoder.getInstance())
.withUser("tom").password("111").roles("ADMIN","USER")
.and()
.withUser("lisi").password("222").roles("USER");
}
同实现自定义UserDetailsService大同小异
此配置会覆盖原先application.yml
中的配置
和自定义UserDetailsService中配置
选其中之一就可以