Rumah > Java > javaTutorial > Bagaimanakah SpringBoot mengintegrasikan SpringSecurityOauth2 untuk melaksanakan isu kebenaran dinamik untuk pengesahan?

Bagaimanakah SpringBoot mengintegrasikan SpringSecurityOauth2 untuk melaksanakan isu kebenaran dinamik untuk pengesahan?

王林
Lepaskan: 2023-05-11 10:28:05
ke hadapan
1514 orang telah melayarinya

Persediaan

spring-boot: 2.1.4.RELEASE

spring-security-oauth3: 2.3.3.RELEASE (Jika anda ingin menggunakan kod sumber, jangan ubah ini nombor versi sesuka hati, kerana 2.4 ditulis secara berbeza)

mysql: 5.7

Paparan kesan

Hanya posmen digunakan untuk ujian di sini, dan halaman hadapan tidak digunakan untuk dok lagi. Seterusnya Akan ada paparan halaman untuk peruntukan kebenaran menu peranan setiap versi

1 Akses antara muka terbuka http://localhost:7000/open/hello

Bagaimanakah SpringBoot mengintegrasikan SpringSecurityOauth2 untuk melaksanakan isu kebenaran dinamik untuk pengesahan?

2 , Akses antara muka yang dilindungi http://localhost:7000/admin/user/info

Bagaimanakah SpringBoot mengintegrasikan SpringSecurityOauth2 untuk melaksanakan isu kebenaran dinamik untuk pengesahan?

tanpa token Log masuk semasa maklumat pengguna

Bagaimanakah SpringBoot mengintegrasikan SpringSecurityOauth2 untuk melaksanakan isu kebenaran dinamik untuk pengesahan?

Bagaimanakah SpringBoot mengintegrasikan SpringSecurityOauth2 untuk melaksanakan isu kebenaran dinamik untuk pengesahan?

Pelaksanaan

oauth3 mempunyai empat mod secara keseluruhan, yang tidak akan dijelaskan di sini mencari dalam talian dan menemui perkara yang sama

Kerana sekarang kami hanya mempertimbangkan aplikasi unilateral, jadi mod kata laluan digunakan.

Akan ada artikel di SpringCloud+Oauth3 nanti, pengesahan get laluan

Mari kita bincangkan beberapa perkara

1 keizinan dinamik konfigurasi pemintas

Bagaimanakah SpringBoot mengintegrasikan SpringSecurityOauth2 untuk melaksanakan isu kebenaran dinamik untuk pengesahan?

Buat kelas MySecurityFilter baharu, warisi AbstractSecurityInterceptor dan laksanakan antara muka Penapis

Permulaan, sesuaikan pengurus keputusan akses

@PostConstruct
 public void init(){
        super.setAuthenticationManager(authenticationManager);
        super.setAccessDecisionManager(myAccessDecisionManager);
  }
Salin selepas log masuk

Penapis tersuai memanggil elemen keselamatan Data sumber

@Override
public SecurityMetadataSource obtainSecurityMetadataSource() {
    return this.mySecurityMetadataSource;
}
Salin selepas log masuk

Mari kita lihat dahulu kod teras penapis tersuai yang memanggil sumber metadata selamat

Kod berikut digunakan untuk mendapatkan kebenaran (peranan) yang diperlukan untuk permintaan semasa untuk masuk

/**
     * 获得当前请求所需要的角色
     * @param object
     * @return
     * @throws IllegalArgumentException
     */
    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        String requestUrl = ((FilterInvocation) object).getRequestUrl();

        if (IS_CHANGE_SECURITY) {
            loadResourceDefine();
        }
        if (requestUrl.indexOf("?") > -1) {
            requestUrl = requestUrl.substring(0, requestUrl.indexOf("?"));
        }
        UrlPathMatcher matcher = new UrlPathMatcher();
        List<Object> list = new ArrayList<>();  //无需权限的,直接返回
        list.add("/oauth/**");
        list.add("/open/**");
        if(matcher.pathsMatchesUrl(list,requestUrl))
            return null;

        Set<String> roleNames = new HashSet();
        for (Resc resc: resources) {
            String rescUrl = resc.getResc_url();
            if (matcher.pathMatchesUrl(rescUrl, requestUrl)) {
                if(resc.getParent_resc_id() != null && resc.getParent_resc_id().intValue() == 1){   //默认权限的则只要登录了,无需权限匹配都可访问
                    roleNames = new HashSet();
                    break;
                }
                Map map = new HashMap();
                map.put("resc_id", resc.getResc_id());
                // 获取能访问该资源的所有权限(角色)
                List<RoleRescDTO> roles = roleRescMapper.findAll(map);
                for (RoleRescDTO rr : roles)
                    roleNames.add(rr.getRole_name());
            }
        }

        Set<ConfigAttribute> configAttributes = new HashSet();
        for(String roleName:roleNames)
            configAttributes.add(new SecurityConfig(roleName));

        log.debug("【所需的权限(角色)】:" + configAttributes);

        return configAttributes;
    }
Salin selepas log masuk

Mari kita lihat kod teras pengurus keputusan akses tersuai Kod ini digunakan terutamanya untuk menentukan sama ada pengguna yang sedang log masuk (peranan yang dimiliki oleh pengguna yang sedang log masuk akan ditulis. dalam item terakhir) mempunyai peranan kebenaran

@Override
    public void decide(Authentication authentication, Object o, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
        if(configAttributes == null){   //属于白名单的,不需要权限
            return;
        }
        Iterator<ConfigAttribute> iterator = configAttributes.iterator();
        while (iterator.hasNext()){
            ConfigAttribute configAttribute = iterator.next();
            String needPermission = configAttribute.getAttribute();
            for (GrantedAuthority ga: authentication.getAuthorities()) {
                if(needPermission.equals(ga.getAuthority())){   //有权限,可访问
                    return;
                }
            }
        }
        throw new AccessDeniedException("没有权限访问");

    }
Salin selepas log masuk

2 Pengecualian pengesahan tersuai mengembalikan hasil yang sama

Mengapa ini diperlukan? hujung dan belakang untuk memahami kandungan yang dikembalikan apabila pengesahan gagal Ia tidak boleh ditafsirkan secara seragam, jadi tanpa berlengah lagi, mari kita lihat situasi pemulangan tanpa konfigurasi dan konfigurasi

(1) Sebelum penyesuaian, apabila. anda tidak membawa token untuk mengakses antara muka API yang dilindungi, hasil yang dikembalikan adalah Seperti ini

Bagaimanakah SpringBoot mengintegrasikan SpringSecurityOauth2 untuk melaksanakan isu kebenaran dinamik untuk pengesahan?

(2) Mari kita tetapkan bahawa selepas antara muka yang gagal pengesahan kembali ke antara muka , ia akan menjadi yang berikut. Adakah lebih baik untuk kita memproses dan menggesa pengguna

Bagaimanakah SpringBoot mengintegrasikan SpringSecurityOauth2 untuk melaksanakan isu kebenaran dinamik untuk pengesahan?

Baiklah, mari kita lihat di mana untuk mengkonfigurasinya Pelayan sumber kami OautyResourceConfig, tulis semula bahagian kod berikut untuk menyesuaikan pengesahan Hasilnya dikembalikan oleh kanan abnormal

Anda boleh merujuk kepada ini https://www.yisu.com/article/131668.htm

@Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.authenticationEntryPoint(authenticationEntryPoint)    //token失效或没携带token时
                .accessDeniedHandler(requestAccessDeniedHandler);   //权限不足时
    }
Salin selepas log masuk

Bagaimanakah SpringBoot mengintegrasikan SpringSecurityOauth2 untuk melaksanakan isu kebenaran dinamik untuk pengesahan? 3. Dapatkan pengguna log masuk Semasa

Yang pertama: gunakan JWT untuk membawa maklumat pengguna, dan kemudian menghuraikannya selepas mendapat token

Tiada penjelasan buat masa ini

Yang kedua: tulis SecurityUser untuk melaksanakan UserDetails Interface (ini adalah yang digunakan dalam projek ini)

Antara muka UserDetails yang asal hanya mempunyai nama pengguna dan kata laluan . Di sini kami menambah Pengguna dalam sistem kami

protected User user;
    public SecurityUser(User user) {
        this.user = user;
    }

    public User getUser() {
        return user;
    }
Salin selepas log masuk

Dalam BaseController, setiap Pengawal Semua akan mewarisi ini, dan menulis kaedah getUser() di dalamnya selagi pengguna membawa token untuk mengakses, kami boleh terus dapatkan maklumat pengguna yang sedang log masuk

protected User getUser() {
        try {
            SecurityUser userDetails = (SecurityUser) SecurityContextHolder.getContext().getAuthentication()
                    .getPrincipal();

            User user = userDetails.getUser();
            log.debug("【用户:】:" + user);

            return user;
        } catch (Exception e) {
        }
        return null;
    }
Salin selepas log masuk

Jadi bagaimana untuk mendapatkannya selepas pengguna berjaya log masuk Bagi koleksi peranan pengguna, dsb., antara muka UserDetailsService mesti dilaksanakan di sini

<🎜? >

@Service
public class TokenUserDetailsService implements UserDetailsService{

    @Autowired
    private LoginService loginService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = loginService.loadUserByUsername(username);  //这个我们拎出来处理
        if(Objects.isNull(user))
            throw new UsernameNotFoundException("用户名不存在");
        return new SecurityUser(user);
    }
}
Salin selepas log masuk

Kemudian dalam kelas konfigurasi keselamatan kami, tetapkan UserDetailsService kepada yang kami tulis di atasBagaimanakah SpringBoot mengintegrasikan SpringSecurityOauth2 untuk melaksanakan isu kebenaran dinamik untuk pengesahan?

@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }
Salin selepas log masuk

Akhirnya kami hanya perlu melaksanakan kami kaedah dalam loginService, dan nilai sama ada pengguna itu wujud berdasarkan pemprosesan perniagaan sebenar kami Bagaimanakah SpringBoot mengintegrasikan SpringSecurityOauth2 untuk melaksanakan isu kebenaran dinamik untuk pengesahan?

@Override
    public User loadUserByUsername(String username){
        log.debug(username);
        Map map = new HashMap();
        map.put("username",username);
        map.put("is_deleted",-1);
        User user = userMapper.findByUsername(map);
        if(user != null){
            map = new HashMap();
            map.put("user_id",user.getUser_id());
            //查询用户的角色
            List<UserRoleDTO> userRoles = userRoleMapper.findAll(map);
            user.setRoles(listRoles(userRoles));
            //权限集合
            Collection<? extends GrantedAuthority> authorities = merge(userRoles);
            user.setAuthorities(authorities);
            return user;
        }
        return null;

    }
Salin selepas log masuk
fail pangkalan data Di Sini

Bagaimanakah SpringBoot mengintegrasikan SpringSecurityOauth2 untuk melaksanakan isu kebenaran dinamik untuk pengesahan?

Atas ialah kandungan terperinci Bagaimanakah SpringBoot mengintegrasikan SpringSecurityOauth2 untuk melaksanakan isu kebenaran dinamik untuk pengesahan?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:yisu.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan