- 新建springboot项目
相关依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--security-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
- security基于内存的方式实现权限认证
application.properties
server.port=8080
config
SecurityConfig
package com.dong.security.config;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//1. 定义用户详细信息服务
@Override
public UserDetailsService userDetailsService(){
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("dong").password(passwordEncoder().encode("123456")).roles("admin").authorities("p1","p2").build());
manager.createUser(User.withUsername("lang").password(passwordEncoder().encode("123456")).roles("student").authorities("p1").build());
//或下面这样写
//manager.createUser(new User("admin",passwordEncoder().encode("123456"), AuthorityUtils.createAuthorityList("p1","p2")));
return manager;
}
//2. 密码编码器(定义密码是否加密等)
//上面的用户信息账户和密码相当于数据库的密码,是正确的密码(接下来需要和我们输入的密码进行比对)
// passwordEncoder.encode() 用于加密密码
// passwordEncoder.matchs(原始密码,加密密码)对比原始密码与加密密码
@Bean
public PasswordEncoder passwordEncoder() {
//加密的方式
return new BCryptPasswordEncoder();
}
//3. 安全拦截机制
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/r/**","/login-success").authenticated() //需要认证才能访问
.antMatchers().hasRole("admin")//需要是admin角色
.anyRequest().permitAll()//其它请求都允许
.and()
.formLogin() //允许基于Form表单登录验证
.successForwardUrl("/login-success")//自定义登录成功的页面地址(可以不写)
.and()
.userDetailsService(userDetailsService());
//补充一下用法
//.antMatchers("/r/**").hasRole("ADMIN") //需要相应的角色才能访问(用户拥有角色时)
//.anyRequest().authenticated() // 任何请求都需要认证
}
}
WebConfig :让首页默认跳转到登录页面
package com.dong.security.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("redirect:/login");
}
}
controller
@RestController
public class LoginController {
//登录成功后的提示信息
@RequestMapping(value = "/login-success" , produces = {"text/plain; charset=UTF-8"})
public String loginSuccess(){
return "登录成功";
}
@RequestMapping(value = "/r/r1" , produces = {"text/plain; charset=UTF-8"})
public String r1(){
return "访问资源r1";
}
@RequestMapping(value = "/r/r2" , produces = {"text/plain; charset=UTF-8"})
public String r2(){
return "访问资源r2";
}
}
- (登录)认证后测试
运行程序访问:http://localhost:8080/ 默认跳转到http://localhost:8080/login显示security自带的登录界面。
输入账户 dong 密码123456 显示:登录成功。
输入账户 lang 密码 123456 显示403:表示没有权限。因为lang不是admi角色而是其它角色。
没登陆前访问:/r/**会跳转到登录界面。
登录成功后访问:http://localhost:8080/r/r1 提示:访问资源r1
访问:http://localhost:8080/logout可以到退出页面(security自带)
- 其它方法实现认证
上面是使用这种方法将用户存入内存
//1. 定义用户详细信息服务
@Override
public UserDetailsService userDetailsService(){
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("dong").password(passwordEncoder().encode("123456")).roles("admin").authorities("p1","p2").build());
manager.createUser(User.withUsername("lang").password(passwordEncoder().encode("123456")).roles("student").authorities("p1").build());
//或下面这样写
//manager.createUser(new User("admin",passwordEncoder().encode("123456"), AuthorityUtils.createAuthorityList("p1","p2")));
return manager;
}
我们还可以使用下面这种方法替换上面的方法将用户存入内存。
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication() //认证信息存储到内存中
.passwordEncoder(passwordEncoder())
.withUser("dong").password(passwordEncoder().encode("123456")).roles("admin")
.authorities("p1","p2");
}
改为这种方式后:安全拦截机制不需要.and().userDetailsService(userDetailsService());
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/r/**","/login-success").authenticated() //需要认证才能访问
.antMatchers().hasRole("admin")//需要是admin角色
.anyRequest().permitAll()//其它请求都允许
.and()
.formLogin() //允许基于Form表单登录验证
.successForwardUrl("/login-success");//自定义登录成功的页面地址(可以不写)
}
- 实现授权
关键语句:antMatchers().hasAnyAuthority()
修改安全拦截机制代码如下
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/r/r1").hasAnyAuthority("p1")
.antMatchers("/r/r2").hasAnyAuthority("p2")
.antMatchers("/r/**","/login-success").authenticated() //需要认证才能访问
.antMatchers().hasRole("admin")//需要是admin角色
.anyRequest().permitAll()//其它请求都允许
.and()
.formLogin() //允许基于Form表单登录验证
.successForwardUrl("/login-success")//自定义登录成功的页面地址(可以不写)
.and()
.userDetailsService(userDetailsService());
}
- 授权后测试
dong拥有p1和p2权限,登录成功后能访问/r/r1和/r/r2
lang拥有p1权限,登录成功后访问/r1/r1正常返回结果,访问/r/r2报403没有权限的错误。