日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring-Boot (四) 集成Spring Security

發布時間:2025/3/15 javascript 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring-Boot (四) 集成Spring Security 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

為什么80%的碼農都做不了架構師?>>> ??

http://nealma.com/2016/04/30/spring-boot-4-security/


### 前言
? ? shiro可以完全解決有關安全的問題,但是項目大多使用的是Spring框架,所以沒必要在引入其他依賴,
? ? so,還是折騰下親兒子的東東吧

開發環境:
OS: Mac 10.11.6
IDE: IDEA
Build: Maven

? ? 以前都是使用xml來配置,但是spring-boot提倡Java Config的使用,
? ? 折騰下來還是很多收獲的。有關權限管理,行內大都秉承
? ? 以角色為基礎的訪問控制(Role-based access control, RBAC)
? ? 在Spring Security中,實現原理很簡單,通過AOP對所要管理的資源(url或者method)進行攔截,
? ? 在其內部維護了一條安全過濾鏈,有用戶服務(UserDetailsService)、身份認證服務(AuthenticationProvider)、
? ? 訪問決策管理(AccessDecisionManager)、記住我(remember-me)等普世功能。
? ? 當然,使用Spring-boot離不開Java Config,come on,just do it.

### WebSecurityConfig

```java

@Configuration
@ComponentScan("com.caogen")
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true)
@PropertySource("classpath:application.properties")
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

? ? protected final Logger LOGGER = LoggerFactory.getLogger(getClass());

? ? @Autowired
? ? private MyAuthenticationProvider authenticationProvider;//自定義驗證

? ? @Autowired
? ? private MyUserDetailsService userDetailsService;

? ? @Autowired
? ? private MyPersistentTokenRepository tokenRepository;

? ? @Autowired
? ? private MyAccessDecisionManager accessDecisionManager;

? ? @Override
? ? protected void configure(AuthenticationManagerBuilder auth) throws Exception {
? ? ? ? auth.authenticationProvider(authenticationProvider);
? ? ? ? auth.userDetailsService(userDetailsService);
? ? }

? ? @Override
? ? protected void configure(HttpSecurity http) throws Exception {
? ? ? ? http
? ? ? ? ? ? ? ? .headers()
? ? ? ? ? ? ? ? ? ? .frameOptions().sameOrigin().disable()//disable X-Frame-Options
? ? ? ? ? ? ? ? .authorizeRequests()
// ? ? ? ? ? ? ? ? ? ?.accessDecisionManager(accessDecisionManager)//用注解替換,如果不使用注解,取消注釋
? ? ? ? ? ? ? ? ? ? .anyRequest().fullyAuthenticated()//其他url需要鑒權
? ? ? ? ? ? ? ? .and()
? ? ? ? ? ? ? ? ? ? .formLogin()
? ? ? ? ? ? ? ? ? ? ? ? .usernameParameter("username")
? ? ? ? ? ? ? ? ? ? ? ? .passwordParameter("password")
? ? ? ? ? ? ? ? ? ? ? ? .loginProcessingUrl("/login")
? ? ? ? ? ? ? ? ? ? ? ? .loginPage("/login")
? ? ? ? ? ? ? ? ? ? ? ? .failureUrl("/login?error")
? ? ? ? ? ? ? ? ? ? ? ? .permitAll()
? ? ? ? ? ? ? ? .and()
? ? ? ? ? ? ? ? ? ? .logout()
? ? ? ? ? ? ? ? ? ? ? ? .deleteCookies("JSESSIONID")
? ? ? ? ? ? ? ? ? ? ? ? .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
? ? ? ? ? ? ? ? ? ? ? ? .logoutSuccessUrl("/login")
? ? ? ? ? ? ? ? .and()
? ? ? ? ? ? ? ? ? ? .rememberMe()
? ? ? ? ? ? ? ? ? ? ? ? .tokenRepository(tokenRepository)
? ? ? ? ? ? ? ? ? ? ? ? .rememberMeServices(rememberMeServices())
? ? ? ? ? ? ? ? ? ? ? ? .rememberMeParameter("remember-me").key("key")
? ? ? ? ? ? ? ? ? ? ? ? .tokenValiditySeconds(86400)
? ? ? ? ? ? ? ? .and()
? ? ? ? ? ? ? ? ? ? .csrf().disable() //disable csrf
? ? ? ? ? ? ? ? ? ? .sessionManagement().maximumSessions(1);
? ? }

? ? @Bean
? ? public RememberMeServices rememberMeServices() {
? ? ? ? // Key must be equal to rememberMe().key()
? ? ? ? PersistentTokenBasedRememberMeServices rememberMeServices =
? ? ? ? ? ? ? ? new PersistentTokenBasedRememberMeServices("key", userDetailsService, tokenRepository);
? ? ? ? rememberMeServices.setCookieName("remember-me");
? ? ? ? rememberMeServices.setParameter("remember-me");
? ? ? ? rememberMeServices.setTokenValiditySeconds(864000);
? ? ? ? return rememberMeServices;
? ? }

}

```

### MyUserDetailsService

```java
/**
?* SPRING SECURITY用戶登錄處理
?*/
@Service("MyUserDetailsServiceImpl")
public class MyUserDetailsService implements UserDetailsService {

? ? protected final Logger LOGGER = LoggerFactory.getLogger(getClass());

? ? @Autowired
? ? private SysUserMapper sysUserMapper;
? ? @Autowired
? ? private RoleMapper roleMapper;
? ? @Autowired
? ? private UserRoleLinkMapper userRoleLinkMapper;

? ? @Autowired
? ? private ResourceService resourceService;
? ? @Override
? ? public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

? ? ? ? LOGGER.info("loadUserByUsername --> [{}]", username);

? ? ? ? SysUser sysUser = new SysUser();
? ? ? ? sysUser.setUsername(username);
? ? ? ? List<SysUser> userList = sysUserMapper.select(sysUser);
? ? ? ? if (userList == null || userList.size() == 0) {
? ? ? ? ? ? throw new UsernameNotFoundException("username not found.");
? ? ? ? }
? ? ? ? sysUser = userList.get(0);
? ? ? ? UserRoleLink userRoleLink = new UserRoleLink();
? ? ? ? userRoleLink.setUserId(sysUser.getId());

? ? ? ? List<UserRoleLink> userRoleLinks = userRoleLinkMapper.select(userRoleLink);
? ? ? ? List<GrantedAuthority> grantedAuthorities = new ArrayList<>();

? ? ? ? List<Long> roleIds = new ArrayList<>();

? ? ? ? Optional<List<UserRoleLink>> userRoleLinksOptional = Optional.ofNullable(userRoleLinks);
? ? ? ? userRoleLinksOptional.ifPresent(userRoleLinks1 -> {
? ? ? ? ? ? userRoleLinks1.forEach(userRoleLink1 -> {
? ? ? ? ? ? ? ? roleIds.add(userRoleLink1.getRoleId());
? ? ? ? ? ? ? ? if(userRoleLink1.getRoleId() == 1L){
? ? ? ? ? ? ? ? ? ? GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_root");//root角色特權
? ? ? ? ? ? ? ? ? ? grantedAuthorities.add(grantedAuthority);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });
? ? ? ? });


// ? ? ? ?List<Role> roles = roleMapper.selectBatch(roleIds);//V1.0
? ? ? ? List<Resource> resources = resourceService.selectByRoleId(roleIds.toArray(new Long[0]));

? ? ? ? if(resources != null && resources.size() > 0){
? ? ? ? ? ? resources.forEach(resource -> {
? ? ? ? ? ? ? ? GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_"+resource.getLink());//必須ROLE_為前綴
? ? ? ? ? ? ? ? grantedAuthorities.add(grantedAuthority);
? ? ? ? ? ? });
? ? ? ? }

? ? ? ? LOGGER.info("grantedAuthorities --> {}", grantedAuthorities);
? ? ? ? return new User(username, sysUser.getPassword(), true, true, true, true, grantedAuthorities);
? ? }

}
```

### MyAuthenticationProvider

```java

/**
?* 自定義驗證方式
?*/
@Component
public class MyAuthenticationProvider implements AuthenticationProvider{

? ? protected final Logger LOGGER = LoggerFactory.getLogger(getClass());

? ? @Autowired
? ? private MyUserDetailsService userService;

? ? @Override
? ? public Authentication authenticate(Authentication authentication)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? throws AuthenticationException {
? ? ? ? String username = authentication.getName();
? ? ? ? String password = (String) authentication.getCredentials();

? ? ? ? UserDetails user = userService.loadUserByUsername(username);

? ? ? ? LOGGER.info("password={}, needPassword={}", password, user.getPassword());
? ? ? ? //密碼匹配驗證
? ? ? ? if (passwordEncoder().matches(password, user.getPassword())) {
? ? ? ? ? ? Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
? ? ? ? ? ? return new UsernamePasswordAuthenticationToken(user, password, authorities);
? ? ? ? }

? ? ? ? throw new BadCredentialsException("Wrong password.");
? ? }

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

? ? @Override
? ? public boolean supports(Class<?> aClass) {
? ? ? ? return true;
? ? }
}

```

### MyAccessDecisionManager

```java
/**
?* 驗證資源跟角色之間的關系
?*/
@Component
public class MyAccessDecisionManager implements AccessDecisionManager {

? ? protected final Logger LOGGER = LoggerFactory.getLogger(getClass());

? ? @Autowired
? ? private RoleService roleService;

? ? /**
? ? ?* // authentication 為用戶所被賦予的權限, configAttributes 為訪問相應的資源應該具有的權限。
? ? ?* @param authentication
? ? ?* @param object
? ? ?* @param configAttributes
? ? ?* @throws AccessDeniedException
? ? ?* @throws InsufficientAuthenticationException
? ? ?*/
? ? @Override
? ? public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
? ? ? ? ? ? throws AccessDeniedException, InsufficientAuthenticationException {

? ? ? ? Collection<GrantedAuthority> userHasRoles =
? ? ? ? ? ? ? ? (Collection<GrantedAuthority>) authentication.getAuthorities();

? ? ? ? LOGGER.info("CurrentUser={} CurrentHasRoles = {}", authentication.getName(), Arrays.asList(userHasRoles));

? ? ? ? //放行[超級管理員]角色
? ? ? ? Iterator<GrantedAuthority> iterator = userHasRoles.iterator();
? ? ? ? while (iterator.hasNext()){
? ? ? ? ? ? GrantedAuthority grantedAuthority = iterator.next();
? ? ? ? ? ? if("系統管理員".equals(grantedAuthority.getAuthority())){
? ? ? ? ? ? ? ? return;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? LOGGER.info("1 CurrentUser={} CurrentHasRoles = {}", authentication.getName(), Arrays.asList(userHasRoles));

? ? ? ? Collection<GrantedAuthority> uriHasRoles = getGrantedAuthoritys(object);
? ? ? ? if (uriHasRoles == null || uriHasRoles.size() == 0) {
? ? ? ? ? ? return;
? ? ? ? }

? ? ? ? Optional<Collection<GrantedAuthority>> grantedAuthoritiesForOptional =
? ? ? ? ? ? ? ? Optional.ofNullable(userHasRoles);

? ? ? ? try{
? ? ? ? ? ? grantedAuthoritiesForOptional.ifPresent(userHasRolesNotNull -> {
? ? ? ? ? ? ? ? userHasRolesNotNull.forEach(userHasRole -> {
? ? ? ? ? ? ? ? ? ? uriHasRoles.forEach(uriHasRole -> {
? ? ? ? ? ? ? ? ? ? ? ? LOGGER.info("userHasRole={}, uriHasRole={}", userHasRole, uriHasRole);
? ? ? ? ? ? ? ? ? ? ? ? if (userHasRole.getAuthority().equals(uriHasRole.getAuthority())) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? throw new AppException("break");
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? });
? ? ? ? ? ? ? ? });
? ? ? ? ? ? });
? ? ? ? }catch(AppException be){
? ? ? ? ? ? return;
? ? ? ? }

? ? ? ? throw new AccessDeniedException("Access Denied.");
? ? }

? ? private Collection<GrantedAuthority> getGrantedAuthoritys(Object object) {
? ? ? ? FilterInvocation filterInvocation = (FilterInvocation) object;
? ? ? ? String uri = new StringBuilder(filterInvocation.getRequestUrl()).deleteCharAt(0).toString();
? ? ? ? if("".equals(uri)){
? ? ? ? ? ? return null;
? ? ? ? }
? ? ? ? List<Role> uriHasRoles = roleService.selectByResourceURI(uri);
? ? ? ? LOGGER.info("fullRequestUrl={}, requestUrl={}, uriHasRoles={}",
? ? ? ? ? ? ? ? filterInvocation.getFullRequestUrl(),
? ? ? ? ? ? ? ? filterInvocation.getRequestUrl(),
? ? ? ? ? ? ? ? uriHasRoles);

? ? ? ? if (uriHasRoles == null || uriHasRoles.size() == 0) {
? ? ? ? ? ? return null;
? ? ? ? }
? ? ? ? Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();
? ? ? ? uriHasRoles.forEach(item -> {
? ? ? ? ? ? GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(item.getName());
? ? ? ? ? ? grantedAuthorities.add(grantedAuthority);
? ? ? ? });
? ? ? ? return grantedAuthorities;
? ? }

? ? @Override
? ? public boolean supports(ConfigAttribute configAttribute) {
? ? ? ? return true;
? ? }

? ? @Override
? ? public boolean supports(Class<?> aClass) {
? ? ? ? return true;
? ? }
}

```

### Remember-Me 使用database方式,MyPersistentTokenRepository

```java

/**
?* 記住我 持久化方式
?*/
@Component
public class MyPersistentTokenRepository implements PersistentTokenRepository {

? ? protected final Logger LOGGER = LoggerFactory.getLogger(getClass());

? ? @Autowired
? ? private RememberMeMapper remembermeMapper;

? ? @Override
? ? public void createNewToken(PersistentRememberMeToken persistentRememberMeToken) {
? ? ? ? RememberMe rememberMe = new RememberMe();
? ? ? ? rememberMe.setUsername(persistentRememberMeToken.getUsername());
? ? ? ? rememberMe.setSeries(persistentRememberMeToken.getSeries());
? ? ? ? rememberMe.setDate(persistentRememberMeToken.getDate());
? ? ? ? rememberMe.setTokenValue(persistentRememberMeToken.getTokenValue());
? ? ? ? remembermeMapper.insert(rememberMe);
? ? }

? ? @Override
? ? public void updateToken(String s, String s1, Date date) {
? ? ? ? RememberMe rememberMe = new RememberMe();
? ? ? ? rememberMe.setUsername("");
? ? ? ? rememberMe.setSeries(s);
? ? ? ? rememberMe.setTokenValue(s1);
? ? ? ? rememberMe.setDate(date);
? ? ? ? remembermeMapper.updateByPK(rememberMe);
? ? }

? ? @Override
? ? public PersistentRememberMeToken getTokenForSeries(String s) {
? ? ? ? RememberMe rememberMe = remembermeMapper.selectByPK(s);
? ? ? ? PersistentRememberMeToken persistentRememberMeToken =
? ? ? ? ? ? ? ? new PersistentRememberMeToken(rememberMe.getUsername(),
? ? ? ? ? ? ? ? ? ? ? ? rememberMe.getSeries(),
? ? ? ? ? ? ? ? ? ? ? ? rememberMe.getTokenValue(),
? ? ? ? ? ? ? ? ? ? ? ? rememberMe.getDate()
? ? ? ? ? ? ? ? );
? ? ? ? return persistentRememberMeToken;
? ? }

? ? @Override
? ? public void removeUserTokens(String s) {
? ? ? ? remembermeMapper.deleteByPK(s);
? ? }
}

```

### 如果用注解的方式,及@RolesAllowed(jsr250)

? ?那么務必將jsr250Enabled=true在config中聲明,然后再所需控制的方法上加上注解,
? ?jsr250有三個注解,分別是@RolesAllowed,@PermitAll,@DenyAll,功能跟名字一樣,
? ?一目了然,如果有多個角色,可以@RolesAllowed({"ROLE_A", "ROLE_B"}),這里角色的前綴
? ?一定是"ROLE_",約定好的,就不要計較了。

### 結束

? ?使用過程中,總是下意識的按照Spring Security提供的思路去實現,無可厚非,但是我仔細琢磨后,
? ?覺得從便利性和實用方面考慮,每個方法上的注解要約定好名稱,例如:

? ?```

? ?@RolesAllowed({"ROLE_roles:view"})
? ?public void find{...}

? ?@RolesAllowed({"ROLE_roles:update"})
? ?public void update{...}

? ?@RolesAllowed({"ROLE_roles:delete"})
? ?public void delete{...}

? ?@RolesAllowed({"ROLE_roles:create"})
? ?public void create{...}

? ?````

? ?這樣,表面是把權限賦予了角色,還能Dynamic Resource,何樂而不為呢。

?

轉載于:https://my.oschina.net/nealma/blog/852586

總結

以上是生活随笔為你收集整理的Spring-Boot (四) 集成Spring Security的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。