この記事は主に SpringBoot+SpringSecurity が Ajax ログインリクエストを処理する問題を紹介しています。この記事は非常によく紹介されているので、必要な友人は参考にしてください。
私は最近プロジェクトでこのような問題に遭遇しました。バックエンド、フロントエンドは Vue で行われ、すべてのデータリクエストは vue-resource を使用して行われ、フォームは使用されないため、データのやり取りはすべて JSON を使用して行われ、Spring Boot がバックグラウンドで使用され、Spring Security が使用されます。はい、今回は単に Ajax リクエストを処理するだけなので、発生した問題をいくつか記録します。ここでのソリューションは、Ajax リクエストに適しているだけでなく、モバイル リクエストの検証も解決します。
プロジェクトを作成する
まず、Spring Boot プロジェクトを作成する必要があります。作成時には、Web、Spring Security、MySQL、MyBatis を導入する必要があります (データベース フレームワークは実際にはオプションです。ここでは MyBatis を使用します)。作成時の依存関係ファイルは次のとおりです。
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.11</version> </dependency>
最後の commons-codec 依存関係は私が手動で追加したものであることに注意してください。これは、MD5 メッセージ ダイジェストの生成に使用できる Apache オープン ソース プロジェクトです。次の記事でパスワードを簡単に分析して対処します。
データベースを作成して構成します
ロジックを簡素化するために、ここでは次のようにユーザー テーブル、ロール テーブル、ユーザー ロール関連付けテーブルの 3 つのテーブルを作成しました。次に、アプリケーションを使用する必要があります。単に .properties でデータベースを構成するだけです。ここでは、特定の状況に応じて決定できます。
spring.datasource.url=jdbc:mysql:///vueblog spring.datasource.username=root spring.datasource.password=123
ここでのユーザークラスは非常に特殊であり、次のように UserDetails インターフェースを実装する必要があります。 UserDetails インターフェイスには、実装する必要があるメソッドがいくつかあります。Boolean を返す 4 つのメソッドはすべて、このフィールドがデータベースに存在するかどうかを示すよく知られたものです。その他はクエリ結果に応じて返されます。単純期間中は、getAuthorities メソッドは現在のユーザーのロール情報を返します。実際には、ロール内のデータが返されます。 GrantedAuthority> ここで注意すべき点があり、データベースに保存するロール名はすべて 'スーパー管理者'、'一般ユーザー' などで始まるので注意してください。 Role エンティティ クラスもあります。これは比較的単純で、データベースのフィールドに従って作成できます。ここでは詳しく説明しません。
UserService を作成するここでの UserService も非常に特殊で、次のように UserDetailsService インターフェースを実装する必要があります:ROLE_
这样的字符开始的,因此需要在这里手动加上 ROLE_
public class User implements UserDetails { private Long id; private String username; private String password; private String nickname; private boolean enabled; private List<Role> roles; @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return enabled; } @Override public List<GrantedAuthority> getAuthorities() { List<GrantedAuthority> authorities = new ArrayList<>(); for (Role role : roles) { authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getName())); } return authorities; } //getter/setter省略... }
UserDetailsService インターフェースを実装した後、このメソッドにloadUserByUsername メソッドを実装する必要があります。インターフェイス、つまりユーザー名クエリユーザーに応じて。 MyBatis の 2 つのマッパーがここに挿入されます。UserMapper はユーザーのクエリに使用され、RolesMapper はロールのクエリに使用されます。 loadUserByUsername メソッドでは、最初に受信パラメーターに基づいてユーザーをクエリします (パラメーターはユーザーのログイン時に入力されたユーザー名です)。見つかったユーザーが null の場合は、処理の便宜のため、UsernameNotFoundException 例外を直接スローできます。 、値を指定せずに User オブジェクトを返したので、その後のパスワード比較プロセスでもログイン失敗が検出されます (見つかったユーザーが null でない場合は、この時点で調整できます)。見つかった値に従ってユーザーを検索し、ユーザー ID を使用してユーザーのロールをクエリし、そのクエリ結果をユーザー オブジェクトの getAuthorities メソッドで使用します。 セキュリティ構成
まず私のセキュリティ構成を見て、それから一つずつ説明していきます:
@Service public class UserService implements UserDetailsService { @Autowired UserMapper userMapper; @Autowired RolesMapper rolesMapper; @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { User user = userMapper.loadUserByUsername(s); if (user == null) { //避免返回null,这里返回一个不含有任何值的User对象,在后期的密码比对过程中一样会验证失败 return new User(); } //查询用户的角色信息,并返回存入user中 List<Role> roles = rolesMapper.getRolesByUid(user.getId()); user.setRoles(roles); return user; } }
これが私たちの構成の中核です、友達、聞いてください1 つずつ:1. まず、これは構成クラスであるため、 @Configuration アノテーションを追加することを忘れないでください。また、これは Spring Security の構成であるため、WebSecurityConfigurerAdapter を継承することを忘れないでください。 2. 作成した UserService を挿入します。これは後で使用します。
3.configure(AuthenticationManagerBuilder auth)方法中用来配置我们的认证方式,在auth.userDetailsService()方法中传入userService,这样userService中的loadUserByUsername方法在用户登录时将会被自动调用。后面的passwordEncoder是可选项,可写可不写,因为我是将用户的明文密码生成了MD5消息摘要后存入数据库的,因此在登录时也需要对明文密码进行处理,所以就加上了passwordEncoder,加上passwordEncoder后,直接new一个PasswordEncoder匿名内部类即可,这里有两个方法要实现,看名字就知道方法的含义,第一个方法encode显然是对明文进行加密,这里我使用了MD5消息摘要,具体的实现方法是由commons-codec依赖提供的;第二个方法matches是密码的比对,两个参数,第一个参数是明文密码,第二个是密文,这里只需要对明文加密后和密文比较即可(小伙伴如果对此感兴趣可以继续考虑密码加盐)。
4.configure(HttpSecurity http)用来配置我们的认证规则等,authorizeRequests方法表示开启了认证规则配置,antMatchers("/admin/**").hasRole("超级管理员")表示 /admin/**
的路径需要有‘超级管理员'角色的用户才能访问,我在网上看到小伙伴对hasRole方法中要不要加 ROLE_
前缀有疑问,这里是不要加的,如果用hasAuthority方法才需要加。anyRequest().authenticated()表示其他所有路径都是需要认证/登录后才能访问。接下来我们配置了登录页面为login_page,登录处理路径为/login,登录用户名为username,密码为password,并配置了这些路径都可以直接访问,注销登陆也可以直接访问,最后关闭csrf。在successHandler中,使用response返回登录成功的json即可,切记不可以使用defaultSuccessUrl,defaultSuccessUrl是只登录成功后重定向的页面,使用failureHandler也是由于相同的原因。
5.configure(WebSecurity web)方法中我配置了一些过滤规则,不赘述。
6.另外,对于静态文件,如 /images/**
、 /css/**
、 /js/**
这些路径,这里默认都是不拦截的。
Controller
最后来看看我们的Controller,如下:
@RestController public class LoginRegController { /** * 如果自动跳转到这个页面,说明用户未登录,返回相应的提示即可 * <p> * 如果要支持表单登录,可以在这个方法中判断请求的类型,进而决定返回JSON还是HTML页面 * * @return */ @RequestMapping("/login_page") public RespBean loginPage() { return new RespBean("error", "尚未登录,请登录!"); } }
这个Controller整体来说还是比较简单的,RespBean一个响应bean,返回一段简单的json,不赘述,这里需要小伙伴注意的是 login_page
,我们配置的登录页面是一个 login_page
,但实际上 login_page
并不是一个页面,而是返回一段JSON,这是因为当我未登录就去访问其他页面时Spring Security会自动跳转到到 login_page
页面,但是在Ajax请求中,不需要这种跳转,我要的只是是否登录的提示,所以这里返回json即可。
测试
最后小伙伴可以使用POSTMAN或者RESTClient等工具来测试登录和权限问题,我就不演示了。
Ok,经过上文的介绍,想必小伙伴们对Spring Boot+Spring Security处理Ajax登录请求已经有所了解了,好了,本文就说到这里,有问题欢迎留言讨论
以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!
相关推荐:
以上がAjax ログイン要求を処理する SpringBoot および SpringSecurity に関する問題の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。