Spring 使用Spring Security实现权限控制
丢代码地址
https://gitee.com/a247292980/spring-security
再丢pom.xml
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity4</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.40</version> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.44</version> </dependency>
最后放个代码结构图
开讲
WebSecurityConfig
spring sercurity的设置。
要有一个实现了UserDetailsService的bean,我的是CustomUserService。
之后,重写两个configure的方法。
@Override protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception { authenticationManagerBuilder.userDetailsService(customUserService()); } /** * 1.首先当我们要自定义Spring Security的时候我们需要继承自WebSecurityConfigurerAdapter来完成,相关配置重写对应 方法即可。 * 2.我们在这里注册CustomUserService的Bean,然后通过重写configure方法添加我们自定义的认证方式。 * 3.在configure(HttpSecurity http)方法中,我们设置了登录页面,而且登录页面任何人都可以访问,然后设置了登录失败地址,也设置了注销请求,注销请求也是任何人都可以访问的。 * 4.permitAll表示该请求任何人都可以访问,.anyRequest().authenticated(),表示其他的请求都必须要有权限认证。 * 5.这里我们可以通过匹配器来匹配路径,比如antMatchers方法,假设我要管理员才可以访问admin文件夹下的内容,我可以这样来写:. * antMatchers("/admin/**").hasRole("ROLE_ADMIN"),也 * 可以设置admin文件夹下的文件可以有多个角色来访问,写法如下: * .antMatchers("/admin/**").hasAnyRole("ROLE_ADMIN","ROLE_USER") * 6.可以通过hasIpAddress来指定某一个ip可以访问该资源,假设只允许访问ip为210.210.210.210的请求获取admin下的资源,写法如下.a * ntMatchers("/admin/**").hasIpAddress("210.210.210.210") */ @Override protected void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity.authorizeRequests() // 留意代码顺序 // 首页(不需要登陆就能访问的页面 .antMatchers("/index").permitAll() .anyRequest().authenticated() // 需要登陆才能访问的页面 .and().formLogin().loginPage("/login").defaultSuccessUrl("/index").failureUrl("/login?error").permitAll() .and().logout().logoutUrl("/logout").logoutSuccessUrl("/login").permitAll() .and().rememberMe().tokenValiditySeconds(60 * 60 * 24 * 7).key("kkkkkkkk"); }
HomeController,BaseEntity,Msg,SysRole
不用多说了,简单的mvc
SysUser
要实现UserDetails接口,重写getAuthorities方法。
里面有个@ManyToMany,虽然代码不配置也行,但这是将两个表关联起来的逻辑。
@Entity public class SysUser extends BaseEntity implements UserDetails { @Id @GeneratedValue private Long id; private String username; private String password; /** * CascadeType.REFRESH:级联刷新,当多个用户同时作操作一个实体,为了用户取到的数据是实时的, * 在用实体中的数据之前就可以调用一下refresh()方法! * FetchType.EAGER:急加载,立即从数据库中加载 */ @ManyToMany(cascade = {CascadeType.REFRESH}, fetch = FetchType.EAGER) private List<SysRole> roles; public void setId(Long id) { this.id = id; } public Long getId() { return this.id; } public void setUsername(String username) { this.username = username; } @Override public String getUsername() { return this.username; } public void setPassword(String password) { this.password = password; } @Override public String getPassword() { return this.password; } public void setRoles(List<SysRole> roles) { this.roles = roles; } public List<SysRole> getRoles() { return this.roles; } @Override public Collection<? extends GrantedAuthority> getAuthorities() { List<GrantedAuthority> grantedAuthorityList = new ArrayList<>(); List<SysRole> sysRoleList = this.getRoles(); for (SysRole sysRole : sysRoleList) { grantedAuthorityList.add(new SimpleGrantedAuthority(sysRole.getName())); } return grantedAuthorityList; } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } }
SysUserRepository
spring-jpa的简单应用
CustomUserService
实现loadUserByUsername的方法,就是传说中的认证方法了,为啥不叫authorize啊?这名字太low了吧。
SpringSecurityApplication
不懂这个的,没关系新建spring boot自带的。