SpringSecurity?Web權(quán)限方案實現(xiàn)全過程
一、設(shè)置登錄系統(tǒng)的賬號、密碼
方式一,配置文件application.properties
spring.security.user.name=lucy spring.security.user.password=123
方式二,編寫配置類
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder(); String password = bCryptPasswordEncoder.encode("123"); auth.inMemoryAuthentication().withUser("zhangsan").password(password).roles("admin"); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
方式三,通過類實現(xiàn)接口UserDetailService
@Service public class userDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException List<GrantedAuthority> list = AuthorityUtils.commaSeparatedStringToAuthorityList("role"); return new User("zhangsan", new BCryptPasswordEncoder().encode("123"), list); } }
二、數(shù)據(jù)庫查詢用戶名密碼
引入依賴
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.0.5</version> </dependency>
建表sql
create table users( id bigint primary key auto_increment, username varchar(20) unique not null, password varchar(100) );
數(shù)據(jù)源配置
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/demo?serverTimezone= GMT%2B8 username: root password: 123456
實體類users
@Getter @Setter @AllArgsConstructor @NoArgsConstructor public class Users { private Integer id; private String username; private String password; }
mapper
@Mapper public interface UserMapper extends BaseMapper<Users> { }
修改userDetailService
@Service public class userDetailsService implements UserDetailsService { @Autowired UserMapper userMapper; @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { // 使用mapper查詢數(shù)據(jù)庫 QueryWrapper<Users> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("username", s); Users users = userMapper.selectOne(queryWrapper); if (users == null) { throw new UsernameNotFoundException("用戶名不存在!"); } List<GrantedAuthority> list = AuthorityUtils.commaSeparatedStringToAuthorityList("role"); return new User(users.getUsername(), new BCryptPasswordEncoder().encode(users.getPassword()), list); } }
修改SecurityConfigTest
@Configuration public class SecurityConfigTest extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
三、自定義登錄頁面
在配置類SpringSecurity中重寫configure方法
@Override protected void configure(HttpSecurity http) throws Exception { http.formLogin() //自定義自己編寫的登錄頁面 .loginPage("/login.html") //登錄頁面設(shè)置 .loginProcessingUrl("/user/login") //登錄訪問路徑 .defaultSuccessUrl("/test/index").permitAll() //登錄成功之后,跳轉(zhuǎn)路徑 .and().authorizeRequests() .antMatchers("/", "/test/hello","/user/login").permitAll() // 設(shè)置哪些路徑可以直接訪問,不需要認證 .anyRequest().authenticated() .and().csrf().disable(); // 關(guān)閉csrf防護 }
再編寫登錄頁面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/user/login" method="post"> 用戶名:<input type="text" name="username"/> <br/> 密碼:<input type="password" name="password"/><br/> <input type="submit" value="login"/> </form> </body> </html>
controlller
@RestController @RequestMapping("/test") public class HelloController { @GetMapping("/hello") public String test() { return "hello, security"; } @GetMapping("/index") public String index() { return "hello, index"; } }
啟動項目后使用的登錄頁面就是我們編寫的 了
四、基于角色或權(quán)限進行訪問控制
(一)hasAuthority 方法
如果當(dāng)前的主體具有指定的權(quán)限,則返回 true,否則返回 false
設(shè)置訪問/test/index需要admin角色
給用戶添加admin角色
修改角色為別的,不是admin后訪問被禁止
(二)hasAnyAuthority 方法
如果當(dāng)前的主體有任何提供的角色(給定的作為一個逗號分隔的字符串列表)的話,返回 true.
(三)hasRole 方法
如果用戶具備給定角色就允許訪問 , 否則出現(xiàn) 403 。
如果當(dāng)前主體具有指定的角色,則返回 true 。
底層源碼:
給用戶添加角色需要加上前綴ROLE_
修改配置文件:
注意配置文件中不需要添加” ROLE_ “,因為上述的底層代碼會自動添加與之進行匹配。
(四)hasAnyRole
表示用戶具備任何一個條件都可以訪問。
給用戶添加角色:
修改配置文件:
五、自定義403頁面
在配置類中配置
編寫unauth頁面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>沒有訪問權(quán)限</h1> </body> </html>
跳轉(zhuǎn)成功
六、注解使用
(一)@Secured
判斷是否具有角色,另外需要注意的是這里匹配的字符串需要添加前綴“ ROLE_ “。
使用注解先要開啟注解功能!
@EnableGlobalMethodSecurity(securedEnabled=true)
@SpringBootApplication @EnableGlobalMethodSecurity(securedEnabled=true) public class DemosecurityApplication { public static void main(String[] args) { SpringApplication.run(DemosecurityApplication.class, args); } }
controller
@GetMapping("/update") @Secured({"ROLE_admin"}) public String update() { return "hello, update"; }
(二)@PreAuthorize
先開啟注解功能:
@EnableGlobalMethodSecurity (prePostEnabled = true )
@PreAuthorize:注解適合進入方法前的權(quán)限驗證, @PreAuthorize 可以將登錄用戶的 roles/permissions 參數(shù)傳到方法中。
@GetMapping("/update") @PreAuthorize("hasAnyAuthority('admin')") public String update() { return "hello, update"; }
(三)@PostAuthorize
先開啟注解功能:
@EnableGlobalMethodSecurity (prePostEnabled = true )
@PostAuthorize 注解使用并不多,在方法執(zhí)行后再進行權(quán)限驗證,適合驗證帶有返回值的權(quán)限.
@RequestMapping("/testPostAuthorize") @ResponseBody @PostAuthorize("hasAnyAuthority('admin')") public String preAuthorize(){ System.out.println("test--PostAuthorize"); return "PostAuthorize"; }
(四)@PreFilter
@PreFilter: 進入控制器之前對數(shù)據(jù)進行過濾
@RequestMapping("getTestPreFilter") @PreAuthorize("hasRole('ROLE_管理員')") @PreFilter(value = "filterObject.id%2==0") @ResponseBody public List<UserInfo> getTestPreFilter(@RequestBody List<UserInfo> list){ list.forEach(t-> { System.out.println(t.getId()+"\t"+t.getUsername()); }); return list; }
(五)@PostFilter
@PostFilter :權(quán)限驗證之后對數(shù)據(jù)進行過濾 留下用戶名是 admin1 的數(shù)據(jù)
表達式中的 filterObject 引用的是方法返回值 List 中的某一個元素
@RequestMapping("getAll") @PreAuthorize("hasRole('ROLE_管理員')") @PostFilter("filterObject.username == 'admin1'") @ResponseBody public List<UserInfo> getAllUser(){ ArrayList<UserInfo> list = new ArrayList<>(); list.add(new UserInfo(1l,"admin1","6666")); list.add(new UserInfo(2l,"admin2","888")); return list; }
七、基于數(shù)據(jù)庫的記住我
使用spring security記住登錄的用戶原理
創(chuàng)建表
CREATE TABLE `persistent_logins` ( `username` varchar(64) NOT NULL, `series` varchar(64) NOT NULL, `token` varchar(64) NOT NULL, `last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`series`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
配置文件編寫數(shù)據(jù)庫的配置
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/demo?serverTimezone= GMT%2B8 username: root password: 123456
配置類
默認 2 周時間。但是可以通過設(shè)置狀態(tài)有效時間,即使項目重新啟動下次也可以正常登錄。
頁面添加記住我復(fù)選框,此處: name 屬性值必須為 remember-me. 不能改為其他值
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/user/login" method="post"> 用戶名:<input type="text" name="username"/> <br/> 密碼:<input type="password" name="password"/><br/> <input type="checkbox" name="remember-me"/>60s內(nèi)免登錄<br/> <input type="submit" value="login"/> </form> </body> </html>
八、CSRF
跨站請求偽造 (英語: Cross-site request forgery ),也被稱為 one-click attack 或者 session riding ,通??s寫為 CSRF 或者 XSRF , 是一種挾制用戶在當(dāng)前已登錄的 Web 應(yīng)用程序上執(zhí)行非本意的操作的攻擊方法。跟 跨網(wǎng)站腳本 ( XSS )相比, XSS 利用的是用戶對指定網(wǎng)站的信任,CSRF 利用的是網(wǎng)站對用戶網(wǎng)頁瀏覽器的信任。
跨站請求攻擊,簡單地說,是攻擊者通過一些技術(shù)手段欺騙用戶的瀏覽器去訪問一個自己曾經(jīng)認證過的網(wǎng)站并運行一些操作(如發(fā)郵件,發(fā)消息,甚至財產(chǎn)操作如轉(zhuǎn)賬和購買商品)。由于瀏覽器曾經(jīng)認證過,所以被訪問的網(wǎng)站會認為是真正的用戶操作而去運行。
這利用了 web 中用戶身份驗證的一個漏洞: 簡單的身份驗證只能保證請求發(fā)自某個用戶的瀏覽 器,卻不能保證請求本身是用戶自愿發(fā)出的 。
從 Spring Security 4.0 開始,默認情況下會啟用 CSRF 保護,以防止 CSRF 攻擊應(yīng)用程序,Spring Security CSRF 會針對 PATCH , POST , PUT 和 DELETE 方法進行防護。
總結(jié)
到此這篇關(guān)于SpringSecurity Web權(quán)限方案實現(xiàn)的文章就介紹到這了,更多相關(guān)SpringSecurity Web權(quán)限內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot集成gzip和zip數(shù)據(jù)壓縮傳輸(適用大數(shù)據(jù)信息傳輸)
?在大數(shù)據(jù)量的傳輸中,壓縮數(shù)據(jù)后進行傳輸可以一定程度的解決速度問題,本文主要介紹了springboot集成gzip和zip數(shù)據(jù)壓縮傳輸,具有一定的參考價值,感興趣的可以了解一下2023-09-09SpringBoot整合新版SpringSecurity完整過程
Spring Security是保障Spring應(yīng)用程序安全的強大框架,而新版的Spring Security引入了lambda表達式來配置,使得安全配置更加簡潔、優(yōu)雅,本文將介紹如何在Spring Boot項目中整合新版Spring Security,需要的朋友可以參考下2024-02-02關(guān)于Java8新特性O(shè)ptional類的詳細解讀
Optional類是一個容器類,它可以保存類型T的值,代表這個值存在?;蛘邇H僅保存null,表示這個值不存在,原來用 null 表示一個值不存在,現(xiàn)在Optional 可以更好的表達這個概念。并且可以避免空指針異常,需要的朋友可以參考下2023-05-05基于servlet實現(xiàn)統(tǒng)計網(wǎng)頁訪問次數(shù)
這篇文章主要為大家詳細介紹了基于servlet實現(xiàn)統(tǒng)計網(wǎng)頁訪問次數(shù),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02