这个demo是基于spring boot+spring security搭建,具体搭建不赘述,只贴上目录和相关代码,并注上解释作为笔记.
目录结构
DemoApplication
package com.spring.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
@EnableGlobalMethodSecurity(prePostEnabled = true) //有这句@PreAuthorize注解才生效
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@RequestMapping("/")
public String hello(){
return "hello spring";
}
@RequestMapping("/hello")
public String helloworld(){
return "helloworld!";
}
@PreAuthorize("hasRole('ROLE_ADMIN')") //方法执行前调用,支持and,or语法,支持表达式
@PostAuthorize("") //方法执行后调用
@RequestMapping("/hi")
public String hiworld(){
return "hi world!";
}
}
DemoApplication类在这里的作用是启动类.并且通过注解@RestController使得这个类成为一个控制器类,另外@EnableAutoConfiguration在spring boot2.2已经整合到@SpringBootApplication中(springboot是通过注解@EnableAutoConfiguration的方式,去查找,过滤,加载所需的configuration,@ComponentScan扫描我们自定义的 bean,@SpringBootConfiguration使得被@SpringBootApplication注解的类声明为注解类.因此@SpringBootApplication的作用等价于同时组合使用@EnableAutoConfiguration,@ComponentScan,@SpringBootConfiguration.)
@PreAuthorize注解可以限定用户登录时的角色,非限定角色无法访问,hasRole(‘ROLE_ADMIN’)中ROLE_是固定写法,后面跟角色名.
SpringSecurityConfig
package com.spring.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MyUserService myUserService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser("admin")
.password(new BCryptPasswordEncoder().encode("123456")).roles("ADMIN");
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser("zhangshan")
.password(new BCryptPasswordEncoder().encode("123456")).roles("ADMIN");
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser("lisi")
.password(new BCryptPasswordEncoder().encode("123456")).roles("USER");
// auth.userDetailsService(myUserService);
// auth.jdbcAuthentication();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/js/**", "/css/**", "/images/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/").permitAll()
.anyRequest().authenticated()
.and()
.logout().permitAll()
.and()
.formLogin();
http.csrf().disable();
}
}
这个类则是SpringSecurity的配置,需要继承WebSecurityConfigurerAdapter并且重写它的几个configure方法.configure(HttpSecurity http)方法在这里是限制请求是否需要认证,而configure(WebSecurity web)方法在这里是忽略静态文件的访问.
MyPasswordEncode
package com.spring.demo;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
public class MyPasswordEncode implements PasswordEncoder {
@Override
public String encode(CharSequence charSequence) {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder.encode(charSequence.toString());
}
@Override
public boolean matches(CharSequence charSequence, String s) {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder.matches(charSequence.toString(),s);
}
}
这个方法暂时没用到,是对密码的加密和验证,用的BCrypt加密算法.
以上能够实现例如当你访问localhost:8008/hi时需要登录认证,并且需要用户角色为ADMIN才可以登录,若用户为USER,则返回一个403forbidden错误.及没有权限访问.