springsecurity輕松實(shí)現(xiàn)角色權(quán)限的示例代碼
問題:
如何在springboot項(xiàng)目中使用springsecurity去實(shí)現(xiàn)角色權(quán)限管理呢?本文將盡可能簡(jiǎn)單的一步步實(shí)現(xiàn)對(duì)接口的角色權(quán)限管理。
項(xiàng)目框架:

sql:
user表:
CREATE TABLE `user` ( `Id` int NOT NULL AUTO_INCREMENT, `UserName` varchar(255) NOT NULL, `CreatedDT` datetime DEFAULT NULL, `Age` int DEFAULT NULL, `Gender` int DEFAULT NULL, `Password` varchar(255) NOT NULL, PRIMARY KEY (`Id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
role表:
CREATE TABLE `role` ( `Id` int NOT NULL AUTO_INCREMENT, `UserId` int DEFAULT NULL, `Role` varchar(255) DEFAULT NULL, `CreatedDT` datetime DEFAULT NULL, PRIMARY KEY (`Id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
maven:
在pom.xml中加入
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--SpringSecurity依賴配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--Hutool Java工具包-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.5.7</version>
</dependency>
model:
實(shí)體類User要實(shí)現(xiàn)springsecurity的基本接口UserDetails,UserDetails里繼承了Serializable,不用擔(dān)心序列化
@Data
public class User implements UserDetails {
public User() {
}
private static final long serialVersionUID = 1L;
private Integer id;
private String userName;
private Date createdDT;
private Integer age;
private Integer gender;
private String passWord;
private String role;
private List<GrantedAuthority> authorities;
public User(String userName, String passWord, List<GrantedAuthority> authorities) {
this.userName = userName;
this.passWord = passWord;
this.authorities = authorities;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return this.passWord;
}
@Override
public String getUsername() {
return this.userName;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
實(shí)體類role:
@Data
public class Role implements Serializable {
private Integer id;
private String role;
private Date createdDT;
private Integer userId;
}
mapper:
@Mapper
public interface UserMapper{
User selectOneByName(User user);
}
service:
public interface UserService{
User selectOneByName(User user) throws ServiceException;
}
serviceImpl:
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper mapper;
@Override
public User selectOneByName(User user) throws ServiceException {
return mapper.selectOneByName(user);
}
}
mapper.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pzh.hyh.demo.mapper.UserMapper"><!-- mapper相對(duì)路徑-->
<resultMap id="BaseResultMap" type="com.pzh.hyh.demo.model.User"><!-- model相對(duì)路徑-->
<result column="Id" jdbcType="INTEGER" property="id"/>
<result column="UserName" jdbcType="VARCHAR" property="userName"/>
<result column="CreatedDT" jdbcType="TIMESTAMP" propert="createdDT"/>
<result column="Age" jdbcType="INTEGER" property="age"/>
<result column="Gender" jdbcType="INTEGER" property="gender"/>
<result column="Password" jdbcType="VARCHAR" property="passWord"/>
</resultMap>
<sql id="Base_Column_List">
Id, UserName, CreatedDT, Age, Gender,Password
</sql>
<select id="selectOneByName" parameterType="com.pzh.hyh.demo.model.User" resultMap="BaseResultMap"><!-- model相對(duì)路徑-->
SELECT u.*,r.role FROM `user` u LEFT JOIN role r on u.Id = r.UserId
where u.UserName = #{userName,jdbcType=VARCHAR}
</select>
</mapper>
config:
首先實(shí)現(xiàn)UserDetailsService類。自定義獲取用戶信息和角色信息。
@Component
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserService userService;
@Autowired
private HttpServletRequest request;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 通過用戶名從數(shù)據(jù)庫(kù)獲取用戶信息
User user = userService.selectOneByName(new User(){
{
setUserName(username);
}
});
if (user == null) {
throw new UsernameNotFoundException("用戶不存在");
}
HttpSession session = request.getSession();
session.setAttribute(session.getId(),user);
// 得到用戶角色
String role = user.getRole();
// 角色集合
List<GrantedAuthority> authorities = new ArrayList<>();
// 角色必須以`ROLE_`開頭,數(shù)據(jù)庫(kù)中沒有,則在這里加
authorities.add(new SimpleGrantedAuthority("ROLE_" + role));
return new User(
user.getUsername(),
user.getPassword(),
authorities
);
}
}
自定義錯(cuò)誤提示
@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
response.getWriter().println("{'code':'403','message':'沒有訪問權(quán)限'}");
response.getWriter().flush();
}
}
終于來到security的配置了
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService userDatailService;
@Autowired
private MyAccessDeniedHandler accessDeniedHandler;
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDatailService)
.passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers().frameOptions().disable()
.and()
.authorizeRequests()
.antMatchers("不限制訪問的路徑,如:'/user/*'").permitAll()
.antMatchers("用戶擁有規(guī)定角色才允許訪問的路徑,如:'/user/delte'").hasRole("admin")
.antMatchers("規(guī)定ip才允許訪問的路徑,如:'/*'").hasIpAddress("192.168.1.1/24");
.anyRequest().authenticated() // 所有請(qǐng)求都需要驗(yàn)證
.and()
// 跳轉(zhuǎn)自定義成功頁(yè)
.formLogin().defaultSuccessUrl("/html/index.html")
.and()
.exceptionHandling()
//用戶無權(quán)限訪問鏈接,給出友好提示
.accessDeniedHandler(accessDeniedHandler)
.and()
.csrf().disable();// post請(qǐng)求要關(guān)閉csrf驗(yàn)證,不然訪問報(bào)錯(cuò);實(shí)際開發(fā)中要開啟。
}
}
至此,springsecurity的角色權(quán)限管理就完成了,如果想要實(shí)現(xiàn)方法級(jí)的角色權(quán)限限制,可以在方法前加入 @PreAuthorize("hasRole('角色')")注解,多個(gè)角色可以使用hasAnyRole(),就可以限制擁有規(guī)定角色權(quán)限的用戶才能訪問了。
@PreAuthorize("hasRole('admin')")
@RequestMapping(value = "/delete")
public CommonResult delete(@RequestBody int id) {
int i = userService.delete(new User() {
{
setId(id);
}
});
return i > 0 ? processSuccess("刪除成功") : processFailure("刪除失敗");
}
到此這篇關(guān)于springsecurity輕松實(shí)現(xiàn)角色權(quán)限的示例代碼的文章就介紹到這了,更多相關(guān)springsecurity 角色權(quán)限內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java網(wǎng)絡(luò)編程之UDP協(xié)議詳細(xì)解讀
這篇文章主要介紹了Java網(wǎng)絡(luò)編程之UDP協(xié)議詳細(xì)解讀,UDP協(xié)議全稱是用戶數(shù)據(jù)報(bào)協(xié)議,在網(wǎng)絡(luò)中它與TCP協(xié)議一樣用于處理數(shù)據(jù)包,是一種無連接的協(xié)議,在OSI模型中,在第四層——傳輸層,處于IP協(xié)議的上一層,需要的朋友可以參考下2023-12-12
SpringBoot中日志切面實(shí)現(xiàn)小結(jié)
本文介紹了SpringBoot中日志切面實(shí)現(xiàn)小結(jié),通過定義一個(gè)自定義注解和創(chuàng)建一個(gè)日志切面類,為方法添加日志記錄功能,感興趣的可以了解一下2024-11-11
Java設(shè)計(jì)模式之單例模式簡(jiǎn)介
這篇文章主要介紹了Java設(shè)計(jì)模式之單例模式簡(jiǎn)介,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)Java的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-04-04
Spring配置文件解析之BeanDefinitionReader詳解
這篇文章主要介紹了Spring配置文件解析之BeanDefinitionReader詳解,ApplicationContext.xml配置文件解析成Document對(duì)象,真正對(duì)xml中元素解析的類是在BeanDefinitionDocumentReader的實(shí)現(xiàn)類中來完成的,需要的朋友可以參考下2024-02-02
分布式醫(yī)療掛號(hào)系統(tǒng)SpringCache與Redis為數(shù)據(jù)字典添加緩存
這篇文章主要為大家介紹了分布式醫(yī)療掛號(hào)系統(tǒng)SpringCache與Redis為數(shù)據(jù)字典添加緩存,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04
SpringBoot2.X Devtools熱部署實(shí)現(xiàn)解析
這篇文章主要介紹了SpringBoot2.X Devtools熱部署實(shí)現(xiàn)解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08

