当前位置: 代码网 > it编程>编程语言>Java > SpringSecurity认证授权全流程解读

SpringSecurity认证授权全流程解读

2025年06月19日 Java 我要评论
springsecurity认证流程:loaduserbyusername()方法内部实现。实现步骤构建一个自定义的service接口,实现springsecurity的userdetailservi

springsecurity认证流程:loaduserbyusername()方法内部实现。

实现步骤

构建一个自定义的service接口,实现springsecurity的userdetailservice接口。

建一个service实现类,实现此loaduserbyusername方法。

调用登录的login接口,会经过authenticationmanager.authenticate(authenticationtoken)方法。此方法会调用loaduserbyusername方法。

方法内部做用户信息的查询,判断用户名和密码是否正确,这是第一道认证。

@service
@requiredargsconstructor
public class userdetailsserviceimpl implements userdetailsservice {


    private final sysusermapper sysusermapper;
    //用户登录请求/login,自动调用方法
    //根据用户名获取用户信息
    //userdetails 存储用户信息,包括用户名,密码,权限
    @override
    public userdetails loaduserbyusername(string username) throws usernamenotfoundexception {
        lambdaquerywrapper<sysuser> wrapper = new lambdaquerywrapper<>();
        wrapper.eq(sysuser::getusername, username);
        sysuser sysuser = sysusermapper.selectone(wrapper);
        if (objects.isnull(sysuser)){
            throw new usernamenotfoundexception("用户名不存在");
        }
        //认证成功回userdetails对象

        return new loginuser(sysuser);
    }


}

@tostring
public class loginuser implements userdetails {

    private sysuser sysuser;

    public loginuser(sysuser sysuser) {
        this.sysuser = sysuser;
    }

    // 权限
    @override
    public collection<? extends grantedauthority> getauthorities() {
        return list.of();
    }

    @override
    public string getpassword() {
        return sysuser.getpassword();
    }

    @override
    public string getusername() {
        return sysuser.getusername();
    }

    // 账号是否过期
    @override
    public boolean isaccountnonexpired() {
        return true;
    }

    // 账号是否被锁定
    @override
    public boolean isaccountnonlocked() {
        return true;
    }

    // 密码是否过期
    @override
    public boolean iscredentialsnonexpired() {
        return true;
    }

    // 账号是否可用
    @override
    public boolean isenabled() {
        return true;
    }
}

如果没有查到信息就抛出异常。

如果查到信息了再接着查用户的权限信息,返回权限信息到loginuser实体。

此实体实现了springsecurity自带的userdetail接口。实现了getauthorities方法。

每次查询权限都会调用此方法。

查询到的权限,会被返回到login接口。进行后续操作。

如果认证通过,通过身份信息中的userid生产一个jwt。

把完整的用户信息作为value,token作为key存入redis。

@restcontroller
@tag(name = "认证模块", description = "认证模块")
@requestmapping("/auth")
@requiredargsconstructor
public class authcontroller {

    //注入authenticationmanager(认证管理器)
    private final authenticationmanager authenticationmanager;

    private final jwtutils jwtutils;

    @postmapping("/login")
    @operation(summary = "登录")
    public result login(@requestparam("username") string username, @requestparam("password") string password) {
        system.out.println(username + password);
        //登录逻辑
        //调用userdetailsservice.loaduserbyusername方法获取
        //不能直接调用,需要通过authenticationmanager进行认证

        authentication authentication = new usernamepasswordauthenticationtoken(username, password);
        authentication authenticate = null;
        try {
            authenticate = authenticationmanager.authenticate(authentication);
        } catch (badcredentialsexception e) {
            return result.failed(resultcode.username_or_password_error);
        }

        //认证成功方法token
        string token=jwtutils.generatetoken(authenticate);
        return result.success(token);
    }
}

@configuration
@enablewebsecurity // 开启web安全
@enablemethodsecurity
@requiredargsconstructor
public class securityconfig {

    private final ignoredurl ignoredurl;


    /**
     * 配置认证管理器 authenticationmanager
     * 作用:用于身份认证
     * 参数:userdetailsservice, passwordencoder
     */
    @bean
    public authenticationmanager authenticationmanager(userdetailsservice userdetailsservice, passwordencoder passwordencoder) {
        daoauthenticationprovider provider = new daoauthenticationprovider();
        provider.setuserdetailsservice(userdetailsservice);
        provider.setpasswordencoder(passwordencoder);
        return new providermanager(provider);
    }

    /**
     * 密码编码器
     *
     * @return
     */
    @bean
    public passwordencoder passwordencoder() {
        return new bcryptpasswordencoder();
    }


    @bean
    public securityfilterchain securityfilterchain(httpsecurity http) throws exception {
        //关闭csrf防护,否则回导致登录失败
        http.csrf(a -> a.disable()); //禁用scrf
        //配置安全拦截规则
        http.authorizehttprequests(req ->
                                   req.requestmatchers(ignoredurl.geturls())
                                   .permitall()
                                   .anyrequest().authenticated());
        /**
         * 配置登录页
         */
        http.formlogin(form -> form
                       .loginpage("/")
                       .successforwardurl("/index") //登录成功跳转页面
                       .loginprocessingurl("/login")//登录处理url
                       .failureforwardurl("/error") //登录失败跳转页面
                       //                .usernameparameter("name")//自定义用户名参数
                       //                .passwordparameter("password")//自定义密码参数
                      );

        return http.build();
    }
}
@component
public class jwtutils {

    @value("${jwt.secret}")
    private string secret;
    @value("${jwt.expiration}")
    private integer expiration;

    /**
     *
     */

    public string generatetoken(authentication authentication) {
        date now = new date();
        date expirationdate = dateutil.offsetsecond(now, expiration);
        map<string, object> claims = new hashmap<>();
        claims.put("username", authentication.getname());//用户名
        claims.put("exp", expirationdate);
        //        claims.put();
        return jwtutil.createtoken(claims, secret.getbytes());
    }
}
@component
@data
@configurationproperties(prefix = "security.ignored")
@tostring
public class ignoredurl {

    private string[] urls;
}

登录成功

登陆失败

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com