Spring Security

spring security一些基本概念和描述此处不多讲,详情请看该文章
spring security参考手册

如果只是单应用服务其实只要security就能完成基本操作,比如登录验证,开放接口,权限操作

OAuth 2.0 主要作用通过对token的验证给予用户认证访问请求,对接第三方校验
OAuth 2.0文档

你可以先让项目跑一下,看下效果,但是这里我整合了oauth2,把spring-security 授权服务配置文件 AuthorizationServerConfig 删掉,就可以先启动 security
GIt项目地址
测试项目用的是jpa,你只需在你数据库里创建一个库,然后配置下datasource 就能自动创建表结构,添加用户信息,密码是用的BCryptPasswordEncoder 生成的,同样也是用该密码解析验证

 public static void main(String[] args) {
        System.out.println(new BCryptPasswordEncoder().encode("123456"));
    }

访问路径:http://localhost:8080/uaa/login
我的账号 admin 密码 123456

下面先理解security的登录校验和权限操作
基于Java的配置

主要是继承 WebSecurityConfigurerAdapter
作用:保护应用程序的URL,验证提交的用户名和密码,重定向到登陆的表单等等

真的是没有太多的配置,但它确实有很多功能.该配置类里东西虽然很多,但我们需要操作的也仅仅是其中的一小部分就可实现基本的功能需求。

需要重写的方法:

	//该方法主要作用是对外开放某些接口,不需要登录验证即可请求访问
	@Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/resource/getResource");
    }
	//主要设置http响应的接口规范
	 @Override
    protected void configure(HttpSecurity http) throws Exception {
	
        http.csrf().disable().authorizeRequests()
                .antMatchers("/resource/**").hasAuthority("EDIT_PATROL")
                /*.antMatchers("/order/**").hasAuthority("EDIT_PATROL")*/
                .anyRequest().permitAll() //其他所有请求都不需要验证
                .and().formLogin();

    }
上面的配置:
	1、取消csrd的安全配置
	2、设置需要拦截的接口信息,及所需要的权限信息
	3、对其他请求不需要验证,但必须是用户的登录状态
	4、允许表单登录

也可以这样设置

@Override
	protected void configure(HttpSecurity http) throws Exception {
	http
		.authorizeRequests()
			.anyRequest().authenticated()
			.and()
		.formLogin()
			.and()
		.httpBasic();
	}
	1、确保我们应用中的所有请求都需要用户被认证
	2、允许用户进行基于表单的认证
	3、允许用户使用HTTP基于验证进行认证	

还可以这样配置,也可以通过formLogin().successForwardUrl() 去配置登录成功后需要访问哪个接口

protected void configure(HttpSecurity http) throws Exception {
	http
		.authorizeRequests()
			.anyRequest().authenticated()
			.and()
		.formLogin()
			.loginPage("/login") 
			.permitAll();        
	}
	1、指定登录页的路径
	2、我们必须允许所有用户访问我们的登录页(例如为验证的用户),
	这个formLogin().permitAll()方法允许基于表单登录的所有的URL的所有用户的访问。

如果在HttpSecurity中描述角色信息和权限信息,security称呼为 web授权

正常项目中我们都是通过从数据读取用户的角色和权限信息,security称呼为方法授权
方法授权需要在任何 @Configuration 实例上使用@EnableGlobalMethodSecurity 注释来启用基于注解的安全性。

使用如下代码可启用prePost注解的支持,

@EnableGlobalMethodSecurity(prePostEnabled = true)

相应的controller层就可以使用方法授权,记得一定要开启prePost注解,否则权限失效

	@RestController
	@RequestMapping("/resource")
	public class ResourceController {


		@PreAuthorize("hasAuthority('p1')")
		@GetMapping("/getResource")
		public String getResource() {
			return "访问资源";
		}

		@GetMapping("/getResource2")
		@PreAuthorize("hasAuthority('EDIT_PATROL')")
		public String getResource2() {
			return "访问资源2";
		}

		@GetMapping("/getUsername")
		public String getUsername() {
			Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
			String username;
			if (principal instanceof UserDetails) {
				username = ((UserDetails) principal).getUsername();
			} else {
				username = principal.toString();
			}
			return username;
		}
	}
你可能会想知道系统提示您登录表单从哪里来的,由于Spring Security的默认配置并没有明确设定一个登录页面的URL,
Spring Security自动生成一个,基于这个功能被启用,使用默认URL处理登录的提交内容,登录后跳转的URL等等。
security默认的登录请求 http://localhost:8080/login
security默认的登出请求 http://localhost:8080/logout

当然还需要告诉security你是用的什么加密方式,在该配置下添加如下,还有其他的加密方式,和直接采用字符串比较的方式就是不加密。

  	@Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

以下是该配置的全部代码,单纯的使用security其实就这么点操作,对应项目需求改改HttpSecurity就完事了

package com.security.demo.config;

	import org.springframework.context.annotation.Bean;
	import org.springframework.context.annotation.Configuration;
	import org.springframework.security.authentication.AuthenticationManager;
	import org.springframework.security.config.BeanIds;
	import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
	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;
	import org.springframework.security.crypto.password.PasswordEncoder;

	@Configuration
	@EnableWebSecurity
	@EnableGlobalMethodSecurity(prePostEnabled = true)
	public class WebSecurityConfigure extends WebSecurityConfigurerAdapter {

		//对外放开某些接口
		@Override
		public void configure(WebSecurity web) throws Exception {
			web.ignoring().antMatchers("/resource/getResource");
		}

		@Override
		protected void configure(HttpSecurity http) throws Exception {
			http.csrf().disable().authorizeRequests()
					.antMatchers("/resource/**").hasAuthority("EDIT_PATROL")
					/*.antMatchers("/order/**").hasAuthority("EDIT_PATROL")*/
					.anyRequest().permitAll() //其他所有请求都不需要验证
					.and().formLogin();

		}

		@Bean
		public PasswordEncoder passwordEncoder() {
			return new BCryptPasswordEncoder();
		}
		//该行代码是设置OAuth2密码授权模式,单纯的security可以不用
		@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
		@Override
		public AuthenticationManager authenticationManagerBean() throws Exception {
			return super.authenticationManagerBean();
		}
	}

当然生产环境中我们都是都过数据库查询来校验用户信息的,所以你还要实现UserDetailsService接口,其实你点进源码,可以看到UserDetailsService该接口就是用来验证用户身份的,只有loadUserByUsername这一个接口信息
在这个接口里就可以实现你自己的用户身份验证逻辑。我这里用到的是jpa查询。你也可以自定义成其他框架查询

	import com.security.demo.entities.User;
	import com.security.demo.repository.UserRepository;
	import org.springframework.beans.factory.annotation.Autowired;
	import org.springframework.security.core.userdetails.UserDetails;
	import org.springframework.security.core.userdetails.UserDetailsService;
	import org.springframework.security.core.userdetails.UsernameNotFoundException;
	import org.springframework.stereotype.Service;

	@Service
	public class UserService implements UserDetailsService {
		@Autowired
		private UserRepository userRepository;

		@Override
		public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

			User user = userRepository.findByUsername(username);
			if (null != user){
				return user;
			}
			return null;
		}
	}

至此配置好你的数据库,和相关的实体类用户角色权限等,我这里用的是jpa配置好数据库后,会自动建表。至于表数据可以自行创建,或者导入我测试的数据

posted @ 2022-01-20 23:22  暮雨寒冬  阅读(201)  评论(0编辑  收藏  举报