shiro学习
一、简介
百度:Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。
其他参考:
1、Apache shiro是Java的一个安全(权限)框架。
2、Shiro可以非常容易的开发出足够好的应用,其不仅可以用在Java SE环境,也可以用在Java EE环境
3、Shiro可以完成:认证、授权、加密、会话管理与Web集成、缓存等。
4、下载:http://shiro.apache.org/
补充:
javaSE包含了基本语法,是Java的基础。是跟桌面应用程序开发相关的类库。
javaEE也包含基本语法,是Java的扩展。是开发Web应用程序的类库。
二、shiro架构
- Subject: 任何可以与应用交互的“用户”。
- SecurityManager:相当于SpringMvc的DispatcherServlet;是Shiro的“心脏”;所有具体的交互都通过SecurityManager进行控制;它管理着所有Subject,且负责进行认证、授权、会话管理以及缓存的管理。
- Realm:可以有1个或多个Realm,可以认为是安全实体数据源,即用于获取安全实体的;可以是JDBC实现,也可以是内存实现等等;由用户提供;所以一般在应用中都需要实现自己的Realm。
三、shiro与Web集成
- 集成Spring
加入Spring和Shiro的jar包
配置Spring及SpringMVC
参照:shiro-root-1.3.2\samples\spring\src\main\webapp\WEB-INF 配置web.xml文件和Spring的配置文件
- 与Web集成
- Shiro 提供了与Web集成的支持,其通过一个ShiroFilter入口来拦截需要安全控制的URL,然后进行相应的控制
- Shior Filter类似于如Strut2/SpringMVC这种web框架的前端控制器,是安全控制的入口点,其负责读取配置(如ini配置文件),然后判断URL是否需要登录/权限等工作。
位置:shiro-root-1.3.2\samples\spring\src\main\webapp\WEB-INF 中的web.xml
其他配置参考shiro配置spring的配置
- 配置后的结果
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
<!-- 静态数据不需要绑定数据源 去掉-->
<!-- Sample RDBMS data source that would exist in any application - not Shiro related. -->
<!-- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:mem:shiro-spring"/>
<property name="username" value="sa"/>
</bean> -->
<!-- 不使用例子 -->
<!-- Populates the sample database with sample users and roles. -->
<!-- <bean id="bootstrapDataPopulator" class="org.apache.shiro.samples.spring.BootstrapDataPopulator">
<property name="dataSource" ref="dataSource"/>
</bean> -->
<!--不使用例子 -->
<!-- Simulated business-tier "Manager", not Shiro related, just an example -->
<!-- <bean id="sampleManager" class="org.apache.shiro.samples.spring.DefaultSampleManager"/> -->
<!-- shiro核心组件
1、配置securityManager
cacheManager:缓存管理器
sessionMode:
-->
<!-- =========================================================
Shiro Core Components - Not Spring Specific
========================================================= -->
<!-- Shiro's main business-tier object for web-enabled applications
(use DefaultSecurityManager instead when there is no web environment)-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="cacheManager" ref="cacheManager"/>
<!-- Single realm app. If you have multiple realms, use the 'realms' property instead. -->
<!-- 配置session管理方式-->
<!-- <property name="sessionMode" value="native"/> -->
<!-- 配置realm -->
<!-- <property name="realm" ref="jdbcRealm"/> -->
<property name="authenticator" ref="authenticator"></property>
<property name="realms">
<list>
<ref bean="jdbcRealm"/>
<ref bean="secondRealm"/>
</list>
</property>
</bean>
<!--
2配置cacheManager
2.1需要加入ehcache的jar包及配置文件ehcache.xml
-->
<!-- Let's use some enterprise caching support for better performance. You can replace this with any enterprise
caching framework implementation that you like (Terracotta+Ehcache, Coherence, GigaSpaces, etc -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<!-- Set a net.sf.ehcache.CacheManager instance here if you already have one. If not, a new one
will be creaed with a default config:
<property name="cacheManager" ref="ehCacheManager"/> -->
<!-- If you don't have a pre-built net.sf.ehcache.CacheManager instance to inject, but you want
a specific Ehcache configuration to be used, specify that here. If you don't, a default
will be used.:-->
<property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/>
</bean>
<!-- Used by the SecurityManager to access security data (users, roles, etc).
Many other realm implementations can be used too (PropertiesRealm,
LdapRealm, etc. -->
<bean id="authenticator" class="org.apache.shiro.authc.pam.ModularRealmAuthenticator">
<!--配置认证策略 -->
<property name="authenticationStrategy">
<bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"></bean>
</property>
</bean>
<!-- 配置Realm
直接配置实现了Realm 实现了org.apache.shiro.realm.Realm的bean
org.apache.shiro.samples.spring.realm.SaltAwareJdbcRealm 替换为
-->
<bean id="jdbcRealm" class="com.atguigu.shiro.realms.shiroAuthRealm">
<!-- <property name="name" value="jdbcRealm"/> -->
<!-- <property name="dataSource" ref="dataSource"/>
<property name="credentialsMatcher">
The 'bootstrapDataPopulator' Sha256 hashes the password
(using the username as the salt) then base64 encodes it:
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="SHA-256"/>
true means hex encoded, false means base64 encoded
<property name="storedCredentialsHexEncoded" value="false"/>
</bean>
</property> -->
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="MD5"></property>
<property name="hashIterations" value="1024"></property>
</bean>
</property>
</bean>
<bean id="secondRealm" class="com.atguigu.shiro.realms.shiroAuthRealm2">
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="SHA1"></property>
<property name="hashIterations" value="1024"></property>
</bean>
</property>
</bean>
<!-- =========================================================
Shiro Spring-specific integration
========================================================= -->
<!-- Post processor that automatically invokes init() and destroy() methods
for Spring-configured Shiro objects so you don't have to
1) specify an init-method and destroy-method attributes for every bean
definition and
2) even know which Shiro objects require these methods to be
called. -->
<!--
4. LifecycleBeanPostProcessor 可以自动的来调用配置Spring IOC容器中shiro
bean的生命周期放方法
-->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- Enable Shiro Annotations for Spring-configured beans. Only run after
the lifecycleBeanProcessor has run: -->
<!-- 5. 启动IOC容器中使用shior的注解,但必须配置了LifecycleBeanPostProcessor 之后才可以使用-->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor"/>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
<!-- Secure Spring remoting: Ensure any Spring Remoting method invocations can be associated
with a Subject for security checks. -->
<!-- 远程调用 -->
<!-- <bean id="secureRemoteInvocationExecutor" class="org.apache.shiro.spring.remoting.SecureRemoteInvocationExecutor">
<property name="securityManager" ref="securityManager"/>
</bean> -->
<!-- Define the Shiro Filter here (as a FactoryBean) instead of directly in web.xml -
web.xml uses the DelegatingFilterProxy to access this bean. This allows us
to wire things with more control as well utilize nice Spring things such as
PropertiesPlaceholderConfigurer and abstract beans or anything else we might need: -->
<!--
6.配置shiroFilter
6.1 id必须和web.xml中的org.springframework.web.filter.DelegatingFilterProxy的name一致
如果不一致则会抛出:NoSuchBeanDefinitionException,因为shiro 会来IOC容器中查找和<filter-name>名字对应的filter bean.
6.2
-->
<bean id="abc" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/login.jsp"/>
<property name="successUrl" value="/list.jsp"/>
<property name="unauthorizedUrl" value="/unauthorized.jsp"/>
<!-- The 'filters' property is not necessary since any declared javax.servlet.Filter bean
defined will be automatically acquired and available via its beanName in chain
definitions, but you can perform overrides or parent/child consolidated configuration
here if you like: -->
<!-- <property name="filters">
<util:map>
<entry key="aName" value-ref="someFilterPojo"/>
</util:map>
</property> -->
<!--
7.配置那些页面需要受保护以及访问这些页面需要的权限
1).anon 可以被匿名访问
2).authc 必须认证才可以访问(登录后)
其他页面不能访问shiro后自动重定向到/login.jsp
3).logout登出
4).roles 角色过滤器
-->
<property name="filterChainDefinitions">
<value>
<!-- /favicon.ico = anon
/logo.png = anon
/shiro.css = anon
/s/login = anon
# allow WebStart to pull the jars for the swing app:
/*.jar = anon
# everything else requires authentication:
/** = authc
logout 表示handler
-->
/login.jsp = anon
/shiro/login = anon
/shiro/logout = logout
/user.jsp = roles[user]
/admin.jsp = roles[admin]
/** = authc
</value>
</property>
</bean>
</beans>
ehcache.xml
<ehcache>
<diskStore path="java.io.tmpdir" />
<cacheManagerEventListenerFactory class="" properties="" />
<!-- need on the cluster environment
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=automatic,
multicastGroupAddress=230.0.0.1,
multicastGroupPort=4446"/>
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"/>
-->
<!--
default cache config
-->
<defaultCache maxElementsInMemory="10000" eternal="true" timeToIdleSeconds="120"
timeToLiveSeconds="120" overflowToDisk="false" diskPersistent="false"
diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" />
</ehcache>
spring-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
">
<context:component-scan base-package="com.atguigu.shiro"></context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<mvc:annotation-driven></mvc:annotation-driven>
<mvc:default-servlet-handler/>
</beans>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name></display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!--监听器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 默认配置文件spring-servlet.xml -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
<url-pattern>*.js</url-pattern>
<url-pattern>*.ttf</url-pattern>
<url-pattern>*.otf</url-pattern>
<url-pattern>*.woff</url-pattern>
<url-pattern>*.woff2</url-pattern>
<url-pattern>*.jpg</url-pattern>
<url-pattern>*.png</url-pattern>
<url-pattern>*.eot</url-pattern>
<url-pattern>*.svg</url-pattern>
<url-pattern>*.PDF</url-pattern>
<url-pattern>*.gif</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 过滤器 -->
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--根据错误编号指定跳转到什么页面-->
<error-page>
<!--当服务器发生了404指定跳转到的界面-->
<error-code>404</error-code>
<location>/WEB-INF/Error/404error.jsp</location>
</error-page>
<!--根据发生什么异常跳转到指定页面-->
<error-page>
<!--算术异常-->
<exception-type>java.lang.ArithmeticException</exception-type>
<location>/WEB-INF/Error/500error.jsp </location>
</error-page>
<!-- ==================================================================
Filters
================================================================== -->
<!-- Shiro Filter is defined in the spring application context: -->
<!--
配置shiro 的shiroFilter
DelegatingFilterProxy实际上是Filter的一个代理对象,默认情况下,Spring会到
IOC容器中查找和<filter-name>对应的filter bean,也可以通过targetBeanName的初始化参数来
配置filter bean的id
-->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>targetBeanName</param-name>
<param-value>abc</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
四、配置
.anon 可以被匿名访问
.authc 必须认证才可以访问(登录后) 其他页面不能访问shiro后自动重定向到/login.jsp
.logout 访问的是Filter过滤器 负责退出登录的
.roles 角色过滤器
五、DelegatingFilterProxy讲解
Web.xml
<!-- 配置shiro 的shiroFilter-->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
applicationContext.xml:
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
目前ShiroFilterFactoryBean的id需要和org.springframework.web.filter.DelegatingFilterProxy的name一致。
如果不一致 会报下面的错误:
首先判断targetBeanName是否为空,为空则使用filter-name中执行的名称
也可以通过 初始化参数targetBeanName
六、Shiro_URL权限配置细节
[urls] 部分的配置,其格式是:“url=拦截器[参数],拦截器[参数]”
如果当前请求的url匹配[urls]部分的某个url模式,将会执行其配置的拦截器
anon(anonymous)拦截器表示匿名访问(既不需要登录即可访问)
authc(authentication)拦截器表示需要身份认证通过后才能访问
shiro中默认的过滤器 | ||
---|---|---|
默认拦截器名 | 拦截器类 | 说明(括号里的表示默认值) |
authc | org.apache.shiro.web.filter.authc. FormAuthenticationFilter | 基于表单的拦截器;如“/**=authc”,如果没有登录会跳到相应的登录页面登录; 主要属性:usernameParam:表单提交的用户名参数名( username); passwordParam:表单提交的密码参数名(password); rememberMeParam:表单提交的密码参数名(rememberMe); loginUrl:登录页面地址(/login.jsp); successUrl:登录成功后的默认重定向地址; failureKeyAttribute:登录失败后错误信息存储key(shiroLoginFailure); |
authcBasic | org.apache.shiro.web.filter.authc .BasicHttpAuthenticationFilter | Basic HTTP身份验证拦截器,主要属性: applicationName:弹出登录框显示的信息(application); |
logout | org.apache.shiro.web.filter.authc .LogoutFilter | 退出拦截器,主要属性:redirectUrl:退出成功后重定向的地址(/);示例“/logout=logout” |
user | org.apache.shiro.web.filter.authc .UserFilter | 用户拦截器,用户已经身份验证/记住我登录的都可;示例“/**=user” |
anon | org.apache.shiro.web.filter.authc .AnonymousFilter | 匿名拦截器,即不需要登录即可访问;一般用于静态资源过滤;示例“/static/**=anon” |
授权相关的 | ||
roles | org.apache.shiro.web.filter.authz .RolesAuthorizationFilter | 角色授权拦截器,验证用户是否拥有所有角色;主要属性: loginUrl:登录页面地址(/login.jsp);unauthorizedUrl:未授权后重定向的地址;示例“/admin/**=roles[admin]” |
perms | org.apache.shiro.web.filter.authz .PermissionsAuthorizationFilter | 权限授权拦截器,验证用户是否拥有所有权限;属性和roles一样;示例“/user/**=perms["user:create"]” |
port | org.apache.shiro.web.filter.authz .PortFilter | 端口拦截器,主要属性:port(80):可以通过的端口;示例“/test= port[80]”,如果用户访问该页面是非80,将自动将请求端口改为80并重定向到该80端口,其他路径/参数等都一样 |
rest | org.apache.shiro.web.filter.authz .HttpMethodPermissionFilter | rest风格拦截器,自动根据请求方法构建权限字符串(GET=read, POST=create,PUT=update,DELETE=delete,HEAD=read,TRACE=read,OPTIONS=read, MKCOL=create)构建权限字符串;示例“/users=rest[user]”,会自动拼出“user:read,user:create,user:update,user:delete”权限字符串进行权限匹配(所有都得匹配,isPermittedAll); |
ssl | org.apache.shiro.web.filter.authz .SslFilter | SSL拦截器,只有请求协议是https才能通过;否则自动跳转会https端口(443); 其他和port拦截器一样; |
其他 | ||
noSessionCreation | org.apache.shiro.web.filter.session .NoSessionCreationFilter | 不创建会话拦截器,调用 subject.getSession(false)不会有什么问题,但是如果 subject.getSession(true) 将抛出 DisabledSessionException异常; |
URL匹配模式
1、url模式使用Ant风格模式
2、Ant路径通配符支持?、*、**,注意通配符匹配不包括目录分隔符“/”:
-?:匹配一个字符,如/admin?将匹配/admin1,但不匹配/admin或/admin/;
-*:匹配零个或多个字符串,如/admin将匹配/admin、/admin123,但不匹配/admin/1;
-**:匹配路径中的零个或多个路径,如/admin/** 将匹配/admin/a或/admin/a/b
URL匹配顺序
1、URL权限采取第一次匹配优先的方式,即从头开始使用第一个匹配的url模式对应的拦截器链
2、如:
- /bb/**=filter1
- /bb/aa=filter2
- /**=filter3
- 如果请求的url是"/bb/aa",因为按照声明顺序进行匹配,那么将使用filter1进行拦截。
七、shior认证思路分析
AuthenticatingRealm :仅仅只是认证的话可以使用这个AuthenticatingRealm
六、实现认证流程
1、login.jsp 表单
2、
3、
/shiro/login = anon
七、实现Realm
八、密码比对
九、密码的加密
1、credentialsMatcher 凭证匹配器
2、
十、MD5盐值加密
Salt 盐值加密
盐值加密:唯一的、最好是username
当用户密码完全一样的时候可以使用盐值加密,是两个用户加密结果不一样
十一、多Realm验证
使用多Realm:将验证放在不同的数据库中
十二、认证策略
认证策略:多个realm怎么才能认证成功
十三、把realms配置给securityManager
1、
十四、授权
十五、授权流程分析
分析使用AuthorizingRealm:
十六、多Realm 授权通过标准
十七、授权分析
十八、Shiro标签
十九、权限注解
注意当Service层有注解@Transactional这时的service已经是一个代理对象,如果在加上shiro注解,就会变成代理的代理,就需要加在Controller层。否则发生类型转换异常
二十、从数据表中初始化资源和权限
配置.配置那些页面需要受保护以及访问这些页面需要的权限 这样配置太过于麻烦如果配置过于太多的话。
分析:
处理过程:
二十一、Shiro____会话管理
在hander层建议使用HttpSession,Shiro中Session意义在于传统Web中Service层不可以使用HttpSession但是现在Shiro中支持非Web的Session.
测试:
二十二、SessionDao
SessionDao:可以把Session写到数据库中,然后对Session进行增、删、改查操作。
二十三、缓存
注意:实际上shiro使用redis做缓存
二十四、记住我
二十五、实现Rememberme功能
补充知识:
一、myeclipse配置class查看源码
1、配置myeclipse可以查看class文件
https://blog.csdn.net/weixin_30776545/article/details/94921603
2、【原创】MyEclipse反编译添加jadclipse_3.3.0 曲折的完美解决
https://blog.csdn.net/lx251845027/article/details/70809404
自己myeclipse配置位置:myeclipse安装路径下
D:\myeclipse2016Work\dropins\plugins 下安装 net.sf.jadclipse_3.3.0.jar
其他操作:按照这个
https://blog.csdn.net/weixin_30776545/article/details/94921603
点击JadClipse,在右边的窗口中配置JadClipse. 设置path to decompiler为jad.exe的全路径,如:C:\jdk\bin\jad.exe,在Directory for temporary files中指定l临时文件路径,如 :D:\Users\Administrator\AppData\Local\Genuitec\MyEclipse-8.6\result ,其中result是新建一个文件夹. 同时需要选中 User Eclipse code formatter ,这样编译出来的Java 代码会和Class文件的格式一样.
为了避免编译后的中文乱码问题,我们需要配置Misc,选中如下单选框.
*.class without source 没有可以点击Add
二、